File Coverage

blib/lib/Message/Router.pm
Criterion Covered Total %
statement 74 74 100.0
branch 50 58 86.2
condition 6 9 66.6
subroutine 8 8 100.0
pod 2 2 100.0
total 140 151 92.7


line stmt bran cond sub pod time code
1             package Message::Router;
2             {
3             $Message::Router::VERSION = '1.132960';
4             }
5              
6 3     3   2438 use strict;use warnings;
  3     3   7  
  3         120  
  3         18  
  3         6  
  3         115  
7 3     3   2534 use Message::Match qw(mmatch);
  3         1937  
  3         248  
8 3     3   2397 use Message::Transform qw(mtransform);
  3         7026  
  3         263  
9             require Exporter;
10 3     3   107 use vars qw(@ISA @EXPORT_OK $config);
  3         5  
  3         2080  
11             @ISA = qw(Exporter);
12             @EXPORT_OK = qw(mroute mroute_config);
13              
14             sub mroute_config {
15 16     16 1 18986 my $new_config;
16 16         25 eval {
17 16 100       58 $new_config = shift
18             or die 'single argument must be a HASH reference';
19 15 100       48 die 'single argument must be a HASH reference'
20             if shift;
21 14 100 33     78 die 'single argument must be a HASH reference'
22             if not $new_config or not ref $new_config eq 'HASH';
23 13 100       39 die "passed config must have an ARRAY or HASH 'routes' key"
24             if not $new_config->{routes};
25 12 100 100     49 if( ref $new_config->{routes} ne 'ARRAY' and
26             ref $new_config->{routes} ne 'HASH') {
27 1         8 die "passed config must have an ARRAY or HASH 'routes' key"
28             }
29 11 100       32 if(ref $new_config->{routes} eq 'ARRAY') {
30 10         12 foreach my $route (@{$new_config->{routes}}) {
  10         19  
31 10 100       24 die "each route must be a HASH reference"
32             if not $route;
33 9 100       29 die "each route must be a HASH reference"
34             if not ref $route eq 'HASH';
35 8 100       23 die "each route has to have a HASH reference 'match' key"
36             if not $route->{match};
37 7 50       19 die "each route has to have a HASH reference 'match' key"
38             if not ref $route->{match} eq 'HASH';
39 7 100       16 if($route->{transform}) {
40 2 100       15 die "the optional 'transform' key must be a HASH reference"
41             if ref $route->{transform} ne 'HASH';
42             }
43 6 50       17 if($route->{forwards}) {
44 6 100       19 die "the optional 'forwards' key must be an ARRAY reference"
45             if ref $route->{forwards} ne 'ARRAY';
46 5         7 foreach my $forward (@{$route->{forwards}}) {
  5         9  
47 5 50       11 die 'each forward must be a HASH reference'
48             if not $forward;
49 5 100       15 die 'each forward must be a HASH reference'
50             if ref $forward ne 'HASH';
51 4 100       26 die "each forward must have a scalar 'handler' key"
52             if not $forward->{handler};
53 3 100       18 die "each forward must have a scalar 'handler' key"
54             if ref $forward->{handler};
55             }
56             }
57             }
58             }
59             };
60 16 100       46 if($@) {
61 13         57 die "Message::Router::mroute_config: $@\n";
62             }
63 3         6 $config = $new_config;
64 3         14 return $config;
65             }
66              
67             sub mroute {
68 5     5 1 1607 eval {
69 5 100       31 my $message = shift or die 'single argument must be a HASH reference';
70 4 100 66     122 die 'single argument must be a HASH reference'
71             unless ref $message and ref $message eq 'HASH';
72 3 50       42 die 'single argument must be a HASH reference'
73             if shift;
74 3         7 my @routes;
75 3 100       16 if(ref $config->{routes} eq 'ARRAY') {
    50          
76 2         4 @routes = @{$config->{routes}};
  2         7  
77             } elsif(ref $config->{routes} eq 'HASH') {
78 1         2 foreach my $order (sort { $a <=> $b } keys %{$config->{routes}}) {
  1         5  
  1         7  
79 2         6 push @routes, $config->{routes}->{$order};
80             }
81             }
82 3         7 foreach my $route (@routes) {
83 4         6 eval {
84 4 50       20 if(mmatch($message, $route->{match})) {
85 3 50       1389 if($route->{transform}) {
86 3         15 mtransform($message, $route->{transform});
87             }
88 3 50       68 if($route->{forwards}) {
89 3         4 foreach my $forward (@{$route->{forwards}}) {
  3         8  
90 3     3   104 no strict 'refs';
  3         21  
  3         592  
91 3         7 &{$forward->{handler}}(
  3         18  
92             message => $message,
93             route => $route,
94             routes => $config->{routes},
95             forward => $forward
96             );
97             }
98             }
99             }
100             };
101 4 100       84 if($@) {
102 1         10 die "Message::Router::mroute: $@\n";
103             }
104             }
105             };
106 5 100       52 if($@) {
107 3         14 die "Message::Router::mmatch: $@\n";
108             }
109 2         11 return 1;
110             }
111             1;
112              
113             __END__
114              
115             =head1 NAME
116              
117             Message::Router - Fast, simple message routing
118              
119             =head1 SYNOPSIS
120              
121             use Message::Router qw(mroute mroute_config);
122              
123             sub main::handler1 {
124             my %args = @_;
125             #gets:
126             # $args{message}
127             # $args{route}
128             # $args{routes}
129             # $args{forward}
130             print "$args{message}->{this}\n"; #from the transform
131             print "$args{forward}->{x}\n"; #from the specific forward
132             }
133              
134             mroute_config({
135             routes => [
136             { match => {
137             a => 'b',
138             },
139             forwards => [
140             { handler => 'main::handler1',
141             x => 'y',
142             },
143             ],
144             transform => {
145             this => 'that',
146             },
147             }
148             ],
149             });
150             mroute({a => 'b'}); #prints 'that', and then 'y', per the handler1 sub
151              
152             mroute_config({
153             routes => {
154             10 => {
155             match => {
156             a => 'b',
157             },
158             forwards => [
159             { handler => 'main::handler1',
160             x => 'y',
161             },
162             ],
163             transform => {
164             this => 'that',
165             },
166             }
167             ],
168             });
169             mroute({a => 'b'}); #prints 'that', and then 'y', per the handler1 sub
170             #same as the ARRAY based, but it uses the HASH keys in numerical order
171              
172             =head1 DESCRIPTION
173              
174             This library allows fast, flexible and general message routing.
175              
176             =head1 FUNCTIONS
177              
178             =head2 mroute_config($config);
179              
180             The config used by all mroute calls
181              
182             =head2 mroute($message);
183              
184             Pass $message through the config; this will emit zero or more callbacks.
185              
186             =head1 TODO
187              
188             A config validator.
189              
190             Short-circuiting
191              
192             More flexible match and transform configuration forms
193              
194             =head1 BUGS
195              
196             None known.
197              
198             =head1 COPYRIGHT
199              
200             Copyright (c) 2012, 2013 Dana M. Diederich. All Rights Reserved.
201              
202             =head1 AUTHOR
203              
204             Dana M. Diederich <dana@realms.org>
205              
206             =cut
207