package Tak::Router;
-use Tak::Request;
+use Tak::MetaService;
+use Scalar::Util qw(weaken);
use Moo;
-has channel => (is => 'ro', required => 1);
+has services => (is => 'ro', default => sub { {} });
-has local_request_handlers => (is => 'ro', default => sub { {} });
-
-has requests_received => (is => 'ro', default => sub { {} });
-
-has last_serial => (is => 'ro',default => sub { 'A0000' });
-
-sub next_serial { ++($_[0]->{last_serial}) }
-
-has requests_sent => (is => 'ro', default => sub { {} });
-
-sub run { shift->run_until }
-
-sub run_until {
- my ($self, $done) = @_;
- while (!$_[1] and my $message = $self->channel->receive) {
- $self->receive(@$message);
- }
+sub BUILD {
+ my ($self) = @_;
+ $self->register(meta => Tak::MetaService->new(router => $self));
}
-sub receive {
- my ($self, $type, @payload) = @_;
- unless ($type) {
- $self->channel->send(MISTAKE => message_format => "No message type");
- return;
- }
- unless (@payload) {
- $self->channel->send(MISTAKE => message_format => "Tag missing");
- return;
- }
- unless (@payload > 1) {
- $self->channel->send(MISTAKE => message_format => "No payload");
- }
- if ($type eq 'REQUEST') {
- $self->receive_request(@payload);
- return;
- }
- if ($type eq 'RESPONSE') {
- $self->receive_response(@payload);
- return;
- }
+sub start_request {
+ my ($self, $req, $target, @payload) = @_;
+ return $req->mistake("Reached router with no target")
+ unless $target;
+ return $req->failure("Reached router with invalid target ${target}")
+ unless my $next = $self->services->{$target};
+ $next->start_request($req, @payload);
}
-sub receive_request {
- my ($self, $tag, $handler_name, @payload) = @_;
- if ($self->requests_received->{$tag}) {
- $self->channel->send(
- MISTAKE => request_tag => "Request for ${tag} in process"
- );
- return;
- }
- my $handler = $self->local_request_handlers->{$handler_name};
- unless ($handler) {
- $self->send_response(
- $tag => MISTAKE => handler_name => "No such handler ${handler_name}"
- );
- return;
- }
- my $request
- = $self->requests_received->{$tag}
- = Tak::Request->new(
- tag => $tag, respond_to => $self, respond_with => 'send_response',
- );
- $handler->start_request($request => @payload);
+sub receive {
+ my ($self, $target, @payload) = @_;
+ return unless $target;
+ return unless my $next = $self->services->{$target};
+ $next->receive(@payload);
}
-sub send_response {
- my ($self, $tag, @result) = @_;
- delete $self->requests_received->{$tag};
- $self->channel->send(RESPONSE => $tag => @result);
+sub register {
+ my ($self, $name, $service) = @_;
+ $self->services->{$name} = $service;
}
-sub send_request {
- my ($self, $respond_to, $respond_with, @payload) = @_;
- my $tag = $self->next_serial;
- my $request
- = $self->requests_sent->{$tag}
- = Tak::Request->new(
- tag => $tag,
- respond_to => $respond_to,
- respond_with => $respond_with,
- );
- $self->channel->send(REQUEST => $tag => @payload);
- return $request;
+sub register_weak {
+ my ($self, $name, $service) = @_;
+ weaken($self->services->{$name} = $service);
}
-sub receive_response {
- my ($self, $tag, @result) = @_;
- my $request = delete $self->requests_sent->{$tag};
- $request->respond(@result);
+sub deregister {
+ my ($self, $name) = @_;
+ delete $self->services->{$name}
}
1;