File Coverage

blib/lib/DBIx/DSN/Resolver/Cached.pm
Criterion Covered Total %
statement 41 45 91.1
branch 14 24 58.3
condition 2 3 66.6
subroutine 8 8 100.0
pod 1 2 50.0
total 66 82 80.4


line stmt bran cond sub pod time code
1             package DBIx::DSN::Resolver::Cached;
2              
3 3     3   75526 use strict;
  3         6  
  3         117  
4 3     3   15 use warnings;
  3         6  
  3         100  
5 3     3   2695 use parent qw/DBIx::DSN::Resolver Exporter/;
  3         960  
  3         17  
6 3     3   150524 use Cache::Memory::Simple;
  3         15482  
  3         115  
7 3     3   31 use Carp;
  3         8  
  3         1959  
8              
9             our $VERSION = '0.04';
10             our @EXPORT = qw/dsn_resolver/;
11             my %RR;
12              
13             sub new {
14 3     3 0 893 my $class = shift;
15 3 50       22 my %args = @_ == 1 ? %{$_[0]} : @_;
  0         0  
16 3 100       14 my $ttl = exists $args{ttl} ? delete $args{ttl} : 5;
17 3 50       13 my $negative_ttl = exists $args{negative_ttl} ? delete $args{negative_ttl} : 1;
18 3 50       43 my $cache = exists $args{cache} ? delete $args{cache} : Cache::Memory::Simple->new;
19             my $resolver = sub {
20 24     24   11184 my $host = shift;
21 24 100       80 if ( my $cached = $cache->get($host) ) {
22 21 50       254 return if @$cached == 0;
23 21 50       46 if ( exists $RR{$host} ) {
24 21         26 $RR{$host}++;
25 21 50       69 $RR{$host} = 0 if $RR{$host} >= scalar @$cached;
26             } else {
27 0         0 $RR{$host} = 0;
28             }
29 21         72 return $cached->[$RR{$host}]
30             }
31 3         45 my ($name,$aliases,$addrtype,$length,@addrs)= gethostbyname($host);
32 2 50       197 if ( ! defined $name ) {
33 0         0 $cache->set($host,[],$negative_ttl);
34 0         0 return;
35             }
36 2         7 my @ipaddr = map { Socket::inet_ntoa($_) } @addrs;
  2         35  
37 2         19 $cache->set($host,\@ipaddr,$ttl);
38 2         99 $RR{$host} = int(rand(scalar @ipaddr));
39 2         13 return $ipaddr[$RR{$host}];
40 3         42 };
41 3         31 $class->SUPER::new(
42             resolver => $resolver
43             );
44             }
45              
46              
47             our $RESOLVER;
48             sub dsn_resolver {
49 3     3 1 794 my $dsn = shift;
50 3 50       12 return unless $dsn;
51 3   66     17 $RESOLVER ||= DBIx::DSN::Resolver::Cached->new();
52 3 50       40 my $resolved = $RESOLVER->resolv($dsn)
53             or croak "Can't resolv dsn: $dsn";
54 2 50       56 return @_ ? ($resolved,@_) : $resolved;
55             }
56              
57             1;
58              
59             __END__