File Coverage

blib/lib/Redis/ScriptCache.pm
Criterion Covered Total %
statement 23 82 28.0
branch 0 30 0.0
condition 0 8 0.0
subroutine 8 17 47.0
pod 7 7 100.0
total 38 144 26.3


line stmt bran cond sub pod time code
1             package Redis::ScriptCache;
2 2     2   34017 use strict;
  2         3  
  2         44  
3 2     2   5 use warnings;
  2         2  
  2         37  
4 2     2   22 use 5.10.0;
  2         7  
5              
6             our $VERSION = '0.05';
7              
8 2     2   7 use File::Basename;
  2         2  
  2         132  
9 2         30 use File::Spec qw(
10             catdir
11             splitdir
12 2     2   7 );
  2         3  
13 2     2   4 use Carp;
  2         2  
  2         99  
14 2     2   1418 use Digest::SHA1 'sha1_hex';
  2         1428  
  2         101  
15              
16             use Class::XSAccessor {
17 2         10 getters => [qw(
18             redis_conn
19             script_dir
20             _script_cache
21             )],
22 2     2   744 };
  2         3322  
23              
24             sub new {
25 0     0 1   my $class = shift;
26 0           my $self = bless { @_ }, $class;
27              
28             # initialize the cache
29 0           $self->{_script_cache} = {};
30             # redis_conn is compulsory
31 0 0         $self->redis_conn
32             or croak('Need Redis connection');
33             # canonicalize script_dir
34 0           $self->_set_script_dir;
35              
36 0           return $self;
37             }
38              
39             sub _set_script_dir {
40 0     0     my( $self, $script_dir ) = @_;
41 0   0       my $script_dir_to_set = $script_dir // $self->script_dir // undef;
      0        
42 0 0         $self->{script_dir} = File::Spec->catdir( File::Spec->splitdir( $script_dir_to_set ) )
43             if $script_dir_to_set;
44 0           return $self;
45             }
46              
47             sub register_all_scripts {
48 0     0 1   my $self = shift;
49 0           my %args = @_;
50              
51             $self->_set_script_dir( $args{script_dir} )
52 0 0         if $args{script_dir};
53              
54 0 0         if ( $self->script_dir ) {
55 0           for my $file (glob($self->script_dir . '/*.lua')) {
56 0           $self->register_file(basename($file));
57             }
58 0           return $self->scripts;
59             } else {
60 0           croak('No script_dir specified');
61             }
62             }
63              
64             sub register_script {
65 0     0 1   my ($self, $script_name, $script) = @_;
66 0 0         $script = $$script if ref($script);
67              
68 0           $self->{_script_cache}{$script_name} = [ sha1_hex($script), $script ];
69              
70 0           return $script_name;
71             }
72              
73             sub run_script {
74 0     0 1   my ($self, $script_name, $args) = @_;
75              
76 0           my $conn = $self->redis_conn;
77 0   0       my $script = $self->_script_cache->{$script_name}
78             // croak("Unknown script $script_name");
79              
80 0           my @result;
81             my $try = sub {
82 0 0   0     $conn->evalsha($$script[0], $args ? @$args : (0));
83 0           };
84 0           my $wantarray = wantarray;
85 0 0         if ( $wantarray ) {
    0          
86 0           @result = eval { $try->() };
  0            
87             }
88             elsif ( defined $wantarray ) {
89 0           $result[0] = eval { $try->() };
  0            
90             }
91             else {
92 0           eval { $try->() };
  0            
93             }
94 0 0         if ( $@ ) {
95 0 0         croak $@ unless $@ =~ /NOSCRIPT/;
96 0 0         return $conn->eval($$script[1], $args ? @$args : (0));
97             };
98              
99 0 0         return unless defined $wantarray;
100 0 0         return $wantarray ? @result : $result[0];
101             }
102              
103             sub register_file {
104 0     0 1   my ($self, $path_to_file) = @_;
105 0 0         open my $fh, '<', File::Spec->catdir( $self->script_dir, $path_to_file )
106             or croak "error opening $path_to_file: $!";
107              
108 0           my $script_name = basename( $path_to_file );
109 0           $script_name =~ s/\.lua$//;
110 0           my $script = do { local $/; <$fh> };
  0            
  0            
111 0           return $self->register_script($script_name, $script);
112             }
113              
114             sub scripts {
115 0     0 1   my ($self) = @_;
116 0           return keys %{ $self->_script_cache };
  0            
117             }
118              
119             sub flush_all_scripts {
120 0     0 1   my ($self) = @_;
121 0           eval {
122 0           $self->redis_conn->script_flush();
123 0           $self->{_script_cache} = {};
124             };
125 0 0         if ( $@ ) {
126 0           croak "redis script_flush failed: $@";
127             };
128 0           return $self;
129             }
130              
131             1;
132              
133             __END__