File Coverage

blib/lib/Plack/Middleware/Proxy/LoadBalancer.pm
Criterion Covered Total %
statement 30 41 73.1
branch 5 8 62.5
condition n/a
subroutine 6 8 75.0
pod 2 3 66.6
total 43 60 71.6


line stmt bran cond sub pod time code
1             package Plack::Middleware::Proxy::LoadBalancer;
2 1     1   631 use strict;
  1         2  
  1         30  
3 1     1   13 use warnings;
  1         2  
  1         26  
4 1     1   5 use parent 'Plack::Middleware';
  1         2  
  1         7  
5              
6 1     1   1078 use Plack::Util::Accessor qw/backends/;
  1         2  
  1         4  
7              
8             our $VERSION = '0.01';
9              
10             sub new {
11 6     6 1 1302 my $class = shift;
12 6 50       53 my %param = ref $_[0] ? %{ $_[0] } : @_;
  6         185  
13              
14 6         28 my $backends = delete $param{backends};
15              
16 6         75 my $self = $class->SUPER::new( \%param );
17 6         194 $self->_set_backends( $backends );
18              
19 6         212 $self;
20             }
21              
22             sub _set_backends{
23 6     6   18 my $self = shift;
24 6         15 my ( $backends ) = @_;
25              
26             # A total of 'weight' should be 1.0
27 6 100       54 if( ref $backends eq 'ARRAY'){
    100          
28 2         21 my $weight = 1 / @$backends;
29 6         126 $self->backends([
30 2         120 map { {remote => $_, weight => $weight} } @$backends
31             ]);
32             }elsif( ref $backends eq 'HASH'){
33 2         15 my $total = 0;
34 2         1402 $total += $_ for values %$backends;
35 6         103 $self->backends([ map {
36 2         20 {remote => $_, weight => $backends->{$_} / $total}
37             } keys %$backends ]);
38             }else{
39 2         67 $self->backends([ { remote => $backends, weight => 1 } ]);
40             }
41             }
42              
43             sub select_backend {
44 0     0 0   my $self = shift;
45 0           my $rand = rand;
46              
47 0           my $choice = undef;
48 0           for( @{ $self->backends } ){
  0            
49 0           $choice = $_->{remote};
50 0 0         ($rand -= $_->{weight}) <= 0 and last;
51             }
52              
53 0           return $choice;
54             }
55              
56             sub call {
57 0     0 1   my ( $self, $env ) = @_;
58 0           $env->{'plack.proxy.remote'} = $self->select_backend;
59 0           $self->app->($env);
60             }
61              
62             1;
63              
64             __END__