object proxying system
[scpubgit/Tak.git] / lib / Tak / ObjectClient.pm
1 package Tak::ObjectClient;
2
3 use Tak::ObjectProxy;
4 use Moo;
5
6 with 'Tak::Role::ObjectMangling';
7
8 has world => (is => 'ro', required => 1);
9
10 has remote => (is => 'lazy');
11
12 sub _build_remote {
13   my ($self) = @_;
14   my $world = $self->world;
15   $world->remote_for('meta')->blocking_request(
16     register => object_service => 'Tak::ObjectService'
17   );
18   $world->remote_for('object_service')
19 }
20
21 sub proxy_method_call {
22   my ($self, @call) = @_;
23   my $ready = $self->encode_objects(\@call);
24   my $context = wantarray;
25   my @res = $self->remote->blocking_request(call_method => $context => $ready);
26   if ($res[0] eq 'RESULT') {
27     my $unpacked = $self->decode_objects($res[1]);
28     if ($context) {
29       return @$unpacked;
30     } elsif (defined $context) {
31       return $unpacked->[0];
32     } else {
33       return;
34     }
35   } else {
36     die $res[1];
37   }
38 }
39
40 sub proxy_death {
41   my ($self, $proxy) = @_;
42   $self->remote->blocking_request(remove_object => $proxy->{tag});
43 }
44
45 sub inflate {
46   my ($self, $tag) = @_;
47   bless({ client => $self, tag => $tag }, 'Tak::ObjectProxy');
48 }
49
50 sub deflate {
51   my ($self, $obj) = @_;
52   unless (ref($obj) eq 'Tak::ObjectProxy') {
53     die "Can't deflate non-proxied object ${obj}";
54   }
55   return +{ __proxied_object__ => $obj->{tag} };
56 }
57
58 sub new_object {
59   my ($self, $class, @args) = @_;
60   $self->proxy_method_call($class, 'new', @args);
61 }
62
63 1;