File Coverage

blib/lib/AnyEvent/JSONRPC/Lite/Client.pm
Criterion Covered Total %
statement 48 59 81.3
branch 6 10 60.0
condition n/a
subroutine 11 12 91.6
pod 3 3 100.0
total 68 84 80.9


line stmt bran cond sub pod time code
1             package AnyEvent::JSONRPC::Lite::Client;
2 9     9   10875 use Any::Moose;
  9         333464  
  9         67  
3              
4 9     9   5202 use Carp;
  9         23  
  9         741  
5 9     9   55 use Scalar::Util 'weaken';
  9         18  
  9         477  
6              
7 9     9   15407 use AnyEvent;
  9         46267  
  9         333  
8 9     9   9229 use AnyEvent::Socket;
  9         63492  
  9         1428  
9 9     9   12520 use AnyEvent::Handle;
  9         79259  
  9         2819  
10              
11             has host => (
12             is => 'ro',
13             isa => 'Str',
14             required => 1,
15             );
16              
17             has port => (
18             is => 'ro',
19             isa => 'Int|Str',
20             required => 1,
21             );
22              
23             has handler => (
24             is => 'rw',
25             isa => 'AnyEvent::Handle',
26             );
27              
28             has on_error => (
29             is => 'rw',
30             isa => 'CodeRef',
31             lazy => 1,
32             default => sub {
33             return sub {
34             my ($handle, $fatal, $message) = @_;
35             croak sprintf "Client got error: %s", $message;
36             };
37             },
38             );
39              
40             has handler_options => (
41             is => 'ro',
42             isa => 'HashRef',
43             default => sub { {} },
44             );
45              
46             has _request_pool => (
47             is => 'ro',
48             isa => 'ArrayRef',
49             lazy => 1,
50             default => sub { [] },
51             );
52              
53             has _next_id => (
54             is => 'ro',
55             isa => 'CodeRef',
56             lazy => 1,
57             default => sub {
58             my $id = 0;
59             sub { ++$id };
60             },
61             );
62              
63             has _callbacks => (
64             is => 'ro',
65             isa => 'HashRef',
66             lazy => 1,
67             default => sub { {} },
68             );
69              
70             has _connection_guard => (
71             is => 'rw',
72             isa => 'Object',
73             );
74              
75 9     9   105 no Any::Moose;
  9         20  
  9         95  
76              
77             sub BUILD {
78 9     9 1 401 my $self = shift;
79              
80             my $guard = tcp_connect $self->host, $self->port, sub {
81 9 50   9   1205 my ($fh) = @_
82             or return
83             $self->on_error->(
84             undef, 1,
85             "Failed to connect $self->{host}:$self->{port}: $!",
86             );
87              
88             my $handle = AnyEvent::Handle->new(
89             on_error => sub {
90 0         0 my ($h, $fatal, $msg) = @_;
91 0         0 $self->on_error->(@_);
92 0         0 $h->destroy;
93             },
94 9         54 %{ $self->handler_options },
  9         120  
95             fh => $fh,
96             );
97              
98             $handle->on_read(sub {
99             shift->unshift_read(json => sub {
100 12         758 $self->_handle_response( $_[1] );
101 12         2846 });
102 9         892 });
103              
104 9         438 while (my $pooled = shift @{ $self->_request_pool }) {
  19         1432  
105 10         51 $handle->push_write( json => $pooled );
106             }
107              
108 9         271 $self->handler( $handle );
109 9         177 };
110 9         5499 weaken $self;
111              
112 9         93 $self->_connection_guard($guard);
113             }
114              
115             sub call {
116 12     12 1 191 my ($self, $method, @params) = @_;
117              
118 12         73 my $request = {
119             id => $self->_next_id->(),
120             method => $method,
121             params => \@params,
122             };
123              
124 12 100       69 if ($self->handler) {
125 2         13 $self->handler->push_write( json => $request );
126             }
127             else {
128 10         18 push @{ $self->_request_pool }, $request;
  10         77  
129             }
130              
131 12         602 $self->_callbacks->{ $request->{id} } = AnyEvent->condvar;
132             }
133              
134             sub _handle_response {
135 12     12   31 my ($self, $res) = @_;
136              
137 12         85 my $d = delete $self->_callbacks->{ $res->{id} };
138 12 50       78 unless ($d) {
139 0         0 warn q/Invalid response from server/;
140 0         0 return;
141             }
142              
143 12 100       65 if (my $error = $res->{error}) {
144 1         11 $d->croak($error);
145             }
146             else {
147 11         54 $d->send($res->{result});
148             }
149             }
150              
151             sub notify {
152 0     0 1   my ($self, $method, @params) = @_;
153              
154 0           my $request = {
155             method => $method,
156             params => \@params,
157             };
158              
159 0 0         if ($self->handler) {
160 0           $self->handler->push_write( json => $request );
161             }
162             else {
163 0           push @{ $self->_request_pool }, $request;
  0            
164             }
165             }
166              
167             __PACKAGE__->meta->make_immutable;
168              
169             __END__