richer expose syntax
[scpubgit/Tak.git] / lib / Tak / MetaService.pm
1 package Tak::MetaService;
2
3 use Tak::WeakClient;
4 use Log::Contextual qw(:log);
5 use Moo;
6
7 with 'Tak::Role::Service';
8
9 has router => (is => 'ro', required => 1, weak_ref => 1);
10
11 sub handle_pid {
12   return $$;
13 }
14
15 sub handle_ensure {
16   my $self = shift;
17   my ($name) = @_;
18   return "Already have ${name}" if $self->router->services->{$name};
19   $self->handle_register(@_);
20 }
21
22 sub handle_register {
23   my ($self, $name, $class, %args) = @_;
24   (my $file = $class) =~ s/::/\//g;
25   require "${file}.pm";
26   if (my $expose = delete $args{expose}) {
27     %args = (%args, %{$self->_construct_exposed_clients($expose)});
28   }
29   my $new = $class->new(\%args);
30   $self->router->register($name => $new);
31   return "Registered ${name}";
32 }
33
34 sub _construct_exposed_clients {
35   my ($self, $expose) = @_;
36   my $router = $self->router;
37   my %client;
38   foreach my $name (keys %$expose) {
39     local $_ = $expose->{$name};
40     if (ref eq 'HASH') {
41       $client{$name} = Tak::Client->new(
42          service => Tak::Router->new(
43            services => $self->_construct_exposed_clients($_)
44          )
45       );
46     } elsif (ref eq 'ARRAY') {
47       if (my ($svc, @rest) = @$_) {
48         die "router has no service ${svc}"
49           unless my $service = $router->services->{$svc};
50         my $client_class = (
51           Scalar::Util::isweak($router->services->{$svc})
52             ? 'Tak::WeakClient'
53             : 'Tak::Client'
54         );
55         $client{$name} = $client_class->new(service => $service)
56                                       ->curry(@rest);
57       } else {
58         $client{$name} = Tak::WeakClient->new(service => $router);
59       }
60     } else {
61       die "expose key ${name} was ".ref;
62     }
63   }
64   \%client;
65 }
66
67 1;