File Coverage

blib/lib/Net/Stomp/MooseHelpers/CanConnect.pm
Criterion Covered Total %
statement 38 38 100.0
branch 6 6 100.0
condition 3 5 60.0
subroutine 13 13 100.0
pod 2 2 100.0
total 62 64 96.8


line stmt bran cond sub pod time code
1             package Net::Stomp::MooseHelpers::CanConnect;
2             $Net::Stomp::MooseHelpers::CanConnect::VERSION = '3.0';
3             {
4             $Net::Stomp::MooseHelpers::CanConnect::DIST = 'Net-Stomp-MooseHelpers';
5             }
6 3     3   3781 use Moose::Role;
  3         8413  
  3         15  
7 3     3   16127 use Net::Stomp::MooseHelpers::Exceptions;
  3         12  
  3         149  
8 3         55 use Net::Stomp::MooseHelpers::Types qw(NetStompish
9             ServerConfigList
10             Headers
11 3     3   1084 );
  3         4959  
12 3     3   10069 use MooseX::Types::Moose qw(CodeRef Bool HashRef);
  3         7  
  3         25  
13 3     3   13088 use Try::Tiny;
  3         7  
  3         184  
14 3     3   43 use namespace::autoclean;
  3         9  
  3         25  
15              
16             # ABSTRACT: role for classes that connect via Net::Stomp
17              
18              
19             has connection => (
20             is => 'rw',
21             isa => NetStompish,
22             lazy_build => 1,
23             );
24              
25              
26             has is_connected => (
27             traits => ['Bool'],
28             is => 'ro',
29             isa => Bool,
30             default => 0,
31             handles => {
32             _set_disconnected => 'unset',
33             _set_connected => 'set',
34             },
35             );
36              
37              
38             has connection_builder => (
39             is => 'rw',
40             isa => CodeRef,
41             default => sub {
42             sub {
43             require Net::Stomp;
44             my $ret = Net::Stomp->new($_[0]);
45             return $ret;
46             }
47             },
48             );
49              
50              
51             has extra_connection_builder_args => (
52             is => 'ro',
53             isa => HashRef,
54             default => sub { {} },
55             );
56              
57             sub _build_connection {
58 12     12   45 my ($self) = @_;
59              
60             return $self->connection_builder->({
61 12         26 %{$self->extra_connection_builder_args},
  12         388  
62             hosts => $self->servers,
63             });
64             }
65              
66              
67             has servers => (
68             is => 'ro',
69             isa => ServerConfigList,
70             lazy => 1,
71             coerce => 1,
72             builder => '_default_servers',
73             traits => ['Array'],
74             handles => {
75             _shift_servers => 'shift',
76             _push_servers => 'push',
77             },
78             );
79             sub _default_servers {
80 1     1   28 [ { hostname => 'localhost', port => 61613 } ]
81             };
82              
83              
84             sub current_server {
85 14     14 1 39 my ($self) = @_;
86              
87 14         371 return $self->servers->[$self->connection->current_host];
88             }
89              
90              
91             has connect_headers => (
92             is => 'ro',
93             isa => Headers,
94             lazy => 1,
95             builder => '_default_connect_headers',
96             );
97 3     3   71 sub _default_connect_headers { { } }
98              
99              
100             sub connect {
101 15     15 1 10532 my ($self) = @_;
102              
103 15 100 66     539 return if $self->has_connection and $self->is_connected;
104              
105             try {
106             # the connection will be created by the lazy builder
107 13     13   902 $self->connection; # needed to make sure that 'current_server'
108             # is the right one
109 13         66 my $server = $self->current_server;
110             my %headers = (
111 13         424 %{$self->connect_headers},
112 13 100       90 %{$server->{connect_headers} || {}},
  13         73  
113             );
114 13         321 my $response = $self->connection->connect(\%headers);
115 9 100       783 if ($response->command eq 'ERROR') {
116 4   50     79 die $response->headers->{message} || 'some STOMP error';
117             }
118 5         190 $self->_set_connected;
119             } catch {
120 8     8   482 Net::Stomp::MooseHelpers::Exceptions::Stomp->throw({
121             stomp_error => $_
122             });
123 13         150 };
124             }
125              
126             1;
127              
128             __END__
129              
130             =pod
131              
132             =encoding UTF-8
133              
134             =head1 NAME
135              
136             Net::Stomp::MooseHelpers::CanConnect - role for classes that connect via Net::Stomp
137              
138             =head1 VERSION
139              
140             version 3.0
141              
142             =head1 SYNOPSIS
143              
144             package MyThing;
145             use Moose; with 'Net::Stomp::MooseHelpers::CanConnect';
146             use Try::Tiny;
147              
148             sub foo {
149             my ($self) = @_;
150             SERVER_LOOP:
151             while (1) {
152             my $exception;
153             try {
154             $self->connect();
155              
156             # do something
157              
158             } catch {
159             $exception = $_;
160             };
161             if ($exception) {
162             if (blessed $exception &&
163             $exception->isa('Net::Stomp::MooseHelpers::Exceptions::Stomp')) {
164             warn "connection died, trying again\n";
165             $self->clear_connection;
166             next SERVER_LOOP;
167             }
168             die "unhandled exception $exception";
169             }
170             }
171             }
172              
173             =head1 DESCRIPTION
174              
175             This role provides your class with a flexible way to connect to a
176             STOMP server. It delegates connecting to one of many server in a
177             round-robin fashion to the underlying L<Net::Stomp>-like library.
178              
179             =head1 ATTRIBUTES
180              
181             =head2 C<connection>
182              
183             The connection to the STOMP server. It's built using the
184             L</connection_builder> (passing L</extra_connection_builder_args>, all
185             L</servers> as C<hosts>, and SSL flag and options). It's usually a
186             L<Net::Stomp> object.
187              
188             =head2 C<is_connected>
189              
190             True if a call to C</connect>
191             succeded. L<Net::Stomp::MooseHelpers::ReconnectOnFailure> resets this
192             when reconnecting; you should not care much about it.
193              
194             =head2 C<connection_builder>
195              
196             Coderef that, given a hashref of options, returns a connection. The
197             default builder just passes the hashref to the constructor of
198             L<Net::Stomp>.
199              
200             =head2 C<extra_connection_builder_args>
201              
202             Optional hashref to pass to the L</connection_builder> when building
203             the L</connection>.
204              
205             =head2 C<servers>
206              
207             A L<ServerConfigList|Net::Stomp::MooseHelpers::Types/ServerConfigList>,
208             that is, an arrayref of hashrefs, each of which describes how to
209             connect to a single server. Defaults to C<< [ { hostname =>
210             'localhost', port => 61613 } ] >>.
211              
212             If a server requires TLS, you can do C<< [ { hostname => $hostname,
213             port => $port, ssl =>1 } ] >>.
214              
215             If a server requires authentication, you can pass the credentials in
216             the C<connect_headers> slot here: C<< [ { hostname => $hostname, port
217             => $port, connect_headers => { login => $login, passcode => $passcode
218             } } ] >>.
219              
220             If all servers require the same authentication, you can instead set
221             the credentials in the L<< /C<connect_headers> >> attribute.
222              
223             =head2 C<connect_headers>
224              
225             Global setting for connection headers (passed to
226             L<Net::Stomp/connect>). Can be overridden by the C<connect_headers>
227             slot in each element of L</servers>. Defaults to the empty hashref.
228              
229             If all servers require the same authentication, you can set the
230             credentials here: C<< { login => $login, passcode => $passcode }
231             >>. If different servers require different credentials, you should set
232             them in the L<< /C<servers> >> attribute instead.
233              
234             =head1 METHODS
235              
236             =head2 C<current_server>
237              
238             Returns the element of L</servers> that the L</connection> says it's
239             connected to.
240              
241             =head2 C<connect>
242              
243             Call the C<connect> method on L</connection>, passing the generic
244             L</connect_headers> and the per-server connect headers (from
245             L</current_server>, slot C<connect_headers>). Throws a
246             L<Net::Stomp::MooseHelpers::Exceptions::Stomp> if anything goes wrong.
247              
248             If the L</connection> attribute is set, and L</is_connected>, returns
249             without doing anything.
250              
251             =head1 AUTHOR
252              
253             Gianni Ceccarelli <gianni.ceccarelli@net-a-porter.com>
254              
255             =head1 COPYRIGHT AND LICENSE
256              
257             This software is copyright (c) 2014 by Net-a-porter.com.
258              
259             This is free software; you can redistribute it and/or modify it under
260             the same terms as the Perl 5 programming language system itself.
261              
262             =cut