File Coverage

blib/lib/Argon/Channel.pm
Criterion Covered Total %
statement 57 64 89.0
branch 1 2 50.0
condition n/a
subroutine 20 21 95.2
pod 1 5 20.0
total 79 92 85.8


line stmt bran cond sub pod time code
1             package Argon::Channel;
2             # ABSTRACT: Line protocol API for non-blocking sockets
3             $Argon::Channel::VERSION = '0.17';
4              
5 3     3   25 use strict;
  3         10  
  3         119  
6 3     3   20 use warnings;
  3         7  
  3         119  
7 3     3   22 use Carp;
  3         8  
  3         211  
8 3     3   1379 use Moose;
  3         2453957  
  3         28  
9 3     3   25853 use AnyEvent;
  3         10  
  3         97  
10 3     3   2215 use AnyEvent::Handle;
  3         25248  
  3         205  
11 3     3   1596 use Argon::Constants qw(:defaults :commands);
  3         12  
  3         754  
12 3     3   1634 use Argon::Log;
  3         12  
  3         344  
13 3     3   1624 use Argon::Marshal qw();
  3         12  
  3         90  
14 3     3   1380 use Argon::Types;
  3         13  
  3         310  
15 3     3   3000 use Argon::Util qw(K);
  3         14  
  3         3886  
16             require Argon::Message;
17              
18              
19             has fh => (
20             is => 'ro',
21             isa => 'FileHandle',
22             required => 1,
23             );
24              
25              
26             has on_msg => (
27             is => 'rw',
28             isa => 'Ar::Callback',
29             default => sub { sub{} },
30             );
31              
32              
33             has on_close => (
34             is => 'rw',
35             isa => 'Ar::Callback',
36             default => sub { sub{} },
37             );
38              
39              
40             has on_err => (
41             is => 'rw',
42             isa => 'Ar::Callback',
43             default => sub { sub{} },
44             );
45              
46             has handle => (
47             is => 'ro',
48             isa => 'Maybe[AnyEvent::Handle]',
49             lazy => 1,
50             builder => '_build_handle',
51             handles => {
52             disconnect => 'push_shutdown',
53             },
54             );
55              
56             sub _build_handle {
57 10     10   28 my $self = shift;
58 10         349 AnyEvent::Handle->new(
59             fh => $self->fh,
60             on_read => K('_read', $self),
61             on_eof => K('_eof', $self),
62             on_error => K('_error', $self),
63             );
64             }
65              
66              
67             sub BUILD {
68 10     10 0 34 my ($self, $args) = @_;
69 10         375 $self->handle;
70             }
71              
72             sub _eof {
73 2     2   11 my ($self, $handle) = @_;
74 2         88 $self->on_close->();
75 2         55 undef $self->{handle};
76             }
77              
78             sub _error {
79 0     0   0 my ($self, $handle, $fatal, $msg) = @_;
80 0         0 log_debug 'Network error: %s', $msg;
81 0         0 $self->on_err->($msg);
82 0         0 $self->disconnect;
83             }
84              
85             sub _read {
86 19     19   46 my $self = shift;
87 19         666 $self->handle->push_read(line => $EOL, K('_readline', $self));
88             }
89              
90             sub _readline {
91 19     19   92 my ($self, $handle, $line) = @_;
92 19         94 my $msg = $self->decode_msg($line);
93 19         109 $self->recv($msg);
94             }
95              
96             sub recv {
97 11     11 0 34 my ($self, $msg) = @_;
98 11         50 log_trace 'recv: %s', $msg->explain;
99 11         1329 $self->on_msg->($msg);
100             }
101              
102              
103             sub send {
104 19     19 1 1108 my ($self, $msg) = @_;
105 19         89 log_trace 'send: %s', $msg->explain;
106              
107 19         1569 my $line = $self->encode_msg($msg);
108              
109 19         18149 eval {
110 19         764 $self->handle->push_write($line);
111 19         3100 $self->handle->push_write($EOL);
112             };
113              
114 19 50       1701 if (my $error = $@) {
115 0         0 log_error 'send: remote host disconnected';
116 0         0 log_debug 'error was: %s', $error;
117 0         0 $self->_eof;
118             };
119             }
120              
121 19     19 0 84 sub encode_msg { Argon::Marshal::encode_msg($_[1]) }
122 19     19 0 5253 sub decode_msg { Argon::Marshal::decode_msg($_[1]) }
123              
124             __PACKAGE__->meta->make_immutable;
125              
126             1;
127              
128             __END__
129              
130             =pod
131              
132             =encoding UTF-8
133              
134             =head1 NAME
135              
136             Argon::Channel - Line protocol API for non-blocking sockets
137              
138             =head1 VERSION
139              
140             version 0.17
141              
142             =head1 SYNOPSIS
143              
144             my $ch = Argon::Channel->new(
145             fh => $socket,
146             on_msg => sub {...},
147             on_close => sub {...},
148             on_err => sub {...}
149             );
150              
151             $ch->send(Argon::Message->new(...));
152              
153             =head1 DESCRIPTION
154              
155             Internal class implementing the line protocol API used for non-blocking socket
156             connections.
157              
158             =head1 ATTRIBUTES
159              
160             =head2 fh
161              
162             File handle for the connected socket. Assumed to be non-blocking.
163              
164             =head2 on_msg
165              
166             A code ref that is called when a new L<Argon::Message> arrives. The message is
167             passed as the only argument.
168              
169             =head2 on_close
170              
171             A code ref that is called when the connection is closed.
172              
173             =head2 on_err
174              
175             A code ref that is called when an error occurs during socket communication. The
176             error message is passed as the only argument.
177              
178             =head1 METHODS
179              
180             =head2 send
181              
182             Sends an L<Argon::Message> over the socket.
183              
184             =head1 AUTHOR
185              
186             Jeff Ober <sysread@fastmail.fm>
187              
188             =head1 COPYRIGHT AND LICENSE
189              
190             This software is copyright (c) 2017 by Jeff Ober.
191              
192             This is free software; you can redistribute it and/or modify it under
193             the same terms as the Perl 5 programming language system itself.
194              
195             =cut