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 = '2.9';
3             {
4             $Net::Stomp::MooseHelpers::CanConnect::DIST = 'Net-Stomp-MooseHelpers';
5             }
6 3     3   3949 use Moose::Role;
  3         7224  
  3         18  
7 3     3   15383 use Net::Stomp::MooseHelpers::Exceptions;
  3         10  
  3         168  
8 3         26 use Net::Stomp::MooseHelpers::Types qw(NetStompish
9             ServerConfigList
10             Headers
11 3     3   1232 );
  3         3995  
12 3     3   8758 use MooseX::Types::Moose qw(CodeRef Bool HashRef);
  3         3  
  3         20  
13 3     3   11137 use Try::Tiny;
  3         9  
  3         189  
14 3     3   14 use namespace::autoclean;
  3         3  
  3         21  
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   20 my ($self) = @_;
59              
60 12         449 return $self->connection_builder->({
61 12         66 %{$self->extra_connection_builder_args},
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   26 [ { hostname => 'localhost', port => 61613 } ]
81             };
82              
83              
84             sub current_server {
85 14     14 1 24 my ($self) = @_;
86              
87 14         429 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   111 sub _default_connect_headers { { } }
98              
99              
100             sub connect {
101 15     15 1 4018 my ($self) = @_;
102              
103 15 100 66     712 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   1123 $self->connection; # needed to make sure that 'current_server'
108             # is the right one
109 13         51 my $server = $self->current_server;
110 13         380 my %headers = (
111 13 100       105 %{$self->connect_headers},
112 13         88 %{$server->{connect_headers} || {}},
113             );
114 13         347 my $response = $self->connection->connect(\%headers);
115 9 100       543 if ($response->command eq 'ERROR') {
116 4   50     30 die $response->headers->{message} || 'some STOMP error';
117             }
118 5         222 $self->_set_connected;
119             } catch {
120 8     8   478 Net::Stomp::MooseHelpers::Exceptions::Stomp->throw({
121             stomp_error => $_
122             });
123 13         169 };
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 2.9
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             =head2 C<connect_headers>
213              
214             Global setting for connection headers (passed to
215             L<Net::Stomp/connect>). Can be overridden by the C<connect_headers>
216             slot in each element of L</servers>. Defaults to the empty hashref.
217              
218             =head1 METHODS
219              
220             =head2 C<current_server>
221              
222             Returns the element of L</servers> that the L</connection> says it's
223             connected to.
224              
225             =head2 C<connect>
226              
227             Call the C<connect> method on L</connection>, passing the generic
228             L</connect_headers> and the per-server connect headers (from
229             L</current_server>, slot C<connect_headers>). Throws a
230             L<Net::Stomp::MooseHelpers::Exceptions::Stomp> if anything goes wrong.
231              
232             If the L</connection> attribute is set, and L</is_connected>, returns
233             without doing anything.
234              
235             =head1 AUTHOR
236              
237             Gianni Ceccarelli <gianni.ceccarelli@net-a-porter.com>
238              
239             =head1 COPYRIGHT AND LICENSE
240              
241             This software is copyright (c) 2014 by Net-a-porter.com.
242              
243             This is free software; you can redistribute it and/or modify it under
244             the same terms as the Perl 5 programming language system itself.
245              
246             =cut