File Coverage

blib/lib/Mojo/Redis2.pm
Criterion Covered Total %
statement 115 316 36.3
branch 29 76 38.1
condition 18 46 39.1
subroutine 28 160 17.5
pod 13 128 10.1
total 203 726 27.9


line stmt bran cond sub pod time code
1             package Mojo::Redis2;
2 32     32   4154974 use Mojo::Base 'Mojo::EventEmitter';
  32         147688  
  32         184  
3              
4 32     32   51879 use Mojo::IOLoop;
  32         3571314  
  32         243  
5 32     32   15952 use Mojo::Redis2::Cursor;
  32         97  
  32         258  
6 32     32   12377 use Mojo::Redis2::Server;
  32         78  
  32         248  
7 32     32   16474 use Mojo::URL;
  32         228750  
  32         272  
8 32     32   1267 use Mojo::Util;
  32         64  
  32         1145  
9 32     32   199 use Carp ();
  32         60  
  32         922  
10 32   50 32   177 use constant DEBUG => $ENV{MOJO_REDIS_DEBUG} || 0;
  32         73  
  32         2324  
11 32     32   192 use constant DEFAULT_PORT => 6379;
  32         65  
  32         118512  
12              
13             our $VERSION = '0.36';
14              
15             my $PROTOCOL_CLASS = do {
16             my $class = $ENV{MOJO_REDIS_PROTOCOL}
17             ||= eval "require Protocol::Redis::XS; 'Protocol::Redis::XS'" || 'Protocol::Redis';
18             eval "require $class; 1" or die $@;
19             $class;
20             };
21              
22             has encoding => 'UTF-8';
23             has protocol_class => $PROTOCOL_CLASS;
24              
25             # DEPRECATED
26             has protocol => sub {
27             Mojo::Util::deprecated('protocol is deprecated in favor or protocol_class');
28             $_[0]->protocol_class->new(api => 1);
29             };
30              
31 1793   100 1793 1 10540 sub url { $_[0]->{url} ||= Mojo::URL->new($ENV{MOJO_REDIS_URL} || 'redis://localhost:6379'); }
      66        
32              
33             sub new {
34 1791     1791 1 16562 my $self = shift->SUPER::new(@_);
35              
36 1791         22785 $self->{name} = Mojo::Util::steady_time if DEBUG;
37              
38 1791 100 66     14007 if ($self->{url} and ref $self->{url} eq '') {
39 1786 100       13220 $self->{url} = "redis://$self->{url}" unless $self->{url} =~ /^redis:/;
40 1786         12289 $self->{url} = Mojo::URL->new($self->{url});
41             }
42              
43 1791         385261 $self;
44             }
45              
46 0     0 1 0 sub blpop { shift->_execute(blpop => BLPOP => @_); }
47 0     0 1 0 sub brpop { shift->_execute(brpop => BRPOP => @_); }
48 0     0 1 0 sub brpoplpush { shift->_execute(brpoplpush => BRPOPLPUSH => @_); }
49              
50             sub bulk {
51 0     0 1 0 my $self = shift;
52 0         0 require Mojo::Redis2::Bulk;
53 0         0 Mojo::Redis2::Bulk->new(_redis => $self);
54             }
55              
56             sub client {
57 0     0 1 0 my $self = shift;
58 0         0 require Mojo::Redis2::Client;
59 0         0 Mojo::Redis2::Client->new(_redis => $self);
60             }
61              
62             sub backend {
63 0     0 1 0 my $self = shift;
64 0         0 require Mojo::Redis2::Backend;
65 0         0 Mojo::Redis2::Backend->new(_redis => $self);
66             }
67              
68             sub multi {
69 0     0 1 0 my $self = shift;
70 0         0 my @attributes = qw( encoding protocol_class url );
71 0         0 require Mojo::Redis2::Transaction;
72 0         0 Mojo::Redis2::Transaction->new(map { $_ => $self->$_ } @attributes);
  0         0  
73             }
74              
75 0     0 1 0 sub psubscribe { shift->_pubsub(PSUBSCRIBE => @_); }
76 0     0 1 0 sub punsubscribe { shift->_pubsub(PUNSUBSCRIBE => @_); }
77 1     1 1 12 sub subscribe { shift->_pubsub(SUBSCRIBE => @_); }
78              
79             sub unsubscribe {
80 0     0 1 0 my $self = shift;
81 0 0       0 return $self->_pubsub(UNSUBSCRIBE => @_) if ref $_[0] eq 'ARRAY';
82 0         0 return $self->SUPER::unsubscribe(@_);
83             }
84              
85 1789     1789   10092 sub DESTROY { $_[0]->{destroy} = 1; $_[0]->_cleanup; }
  1789         6025  
86              
87             sub _basic_operations {
88 32     32   464 'append', 'bitcount', 'bitop', 'bitpos', 'decr', 'decrby', 'del', 'echo', 'eval', 'evalsha', 'exists', 'expire',
89             'expireat', 'get', 'getbit', 'getrange', 'getset', 'geoadd', 'geodist', 'geohash', 'geopos', 'georadius',
90             'georadiusbymember', 'hdel', 'hexists', 'hget', 'hgetall', 'hincrby', 'hincrbyfloat', 'hkeys', 'hlen', 'hmget',
91             'hmset', 'hset', 'hsetnx', 'hstrlen', 'hvals', 'incr', 'incrby', 'incrbyfloat', 'keys', 'lindex', 'linsert',
92             'llen', 'lpop', 'lpush', 'lpushx', 'lrange', 'lrem', 'lset', 'ltrim', 'mget', 'move', 'mset', 'msetnx', 'persist',
93             'pexpire', 'pexpireat', 'pfadd', 'pfcount', 'pfmerge', 'ping', 'psetex', 'pttl', 'publish', 'randomkey', 'rename',
94             'renamenx', 'rpop', 'rpoplpush', 'rpush', 'rpushx', 'sadd', 'scard', 'sdiff', 'sdiffstore', 'set', 'setbit',
95             'setex', 'setnx', 'setrange', 'sinter', 'sinterstore', 'sismember', 'smembers', 'smove', 'sort', 'spop',
96             'srandmember', 'srem', 'strlen', 'sunion', 'sunionstore', 'ttl', 'type', 'zadd', 'zcard', 'zcount', 'zincrby',
97             'zinterstore', 'zlexcount', 'zrange', 'zrangebylex', 'zrangebyscore', 'zrank', 'zrem', 'zremrangebylex',
98             'zremrangebyrank', 'zremrangebyscore', 'zrevrange', 'zrevrangebylex', 'zrevrangebyscore', 'zrevrank', 'zscore',
99             'zunionstore';
100             }
101              
102 3564     3564   19086 sub _blocking_group {'blocking'}
103              
104             sub _cleanup {
105 1789     1789   3213 my $self = shift;
106 1789         3714 my $connections = delete $self->{connections};
107              
108 1789         4217 delete $self->{pid};
109              
110 1789         5608 for my $c (values %$connections) {
111 1784 50       5040 my $loop = $self->_loop($c->{nb}) or next;
112 1784 100       4598 $loop->remove($c->{id}) if $c->{id};
113 1784         3435 $self->$_('Premature connection close', []) for grep {$_} map { $_->[0] } @{$c->{waiting}};
  2         9  
  2         6  
  1784         38426  
114             }
115             }
116              
117             sub _connect {
118 1788     1788   4285 my ($self, $c) = @_;
119 1788         4738 my $url = $self->url;
120 1788         15288 my $db = $url->path->[0];
121 1788   100     137455 my @userinfo = split /:/, +($url->userinfo // '');
122              
123 1788         21236 Scalar::Util::weaken($self);
124 1788         6578 $c->{protocol} = $self->protocol_class->new(api => 1);
125 1788         62937 $c->{name} = "$self->{name}:$c->{group}:$c->{nb}" if DEBUG;
126             $c->{id} = $self->_loop($c->{nb})->client(
127             {address => $url->host, port => $url->port || DEFAULT_PORT},
128             sub {
129 1786     1786   1882347 my ($loop, $err, $stream) = @_;
130              
131 1786 100       5604 if ($err) {
132 1782         4172 delete $c->{id};
133 1782         6654 return $self->_error($c, $err);
134             }
135              
136 4         5 warn "[$c->{name}] --- @{[$self->_debug_url($url, $c)]}\n" if DEBUG;
137              
138 4         12 $stream->timeout(0);
139 4 0       112 $stream->on(close => sub { $self and $self->_error($c) });
  0         0  
140 4 0       44 $stream->on(error => sub { $self and $self->_error($c, $_[1]) });
  0         0  
141 4 0       30 $stream->on(read => sub { $self and $self->_read($c, $_[1]) });
  0         0  
142              
143             # NOTE: unshift() will cause AUTH to be sent before SELECT
144 4 100       23 unshift @{$c->{queue}}, [undef, SELECT => $db] if $db;
  2         8  
145 4 100       20 unshift @{$c->{queue}}, [undef, AUTH => $userinfo[1]] if length $userinfo[1];
  1         5  
146              
147 4         11 $self->emit(connection => {map { $_ => $c->{$_} } qw( group id nb )});
  12         44  
148 4         49 $self->_dequeue($c);
149             },
150 1788   100     7022 );
151              
152 1788         556698 $self;
153             }
154              
155             sub _debug_url {
156 0     0   0 my $self = shift;
157 0         0 my $url = shift->clone;
158 0         0 my $c = shift;
159              
160 0 0       0 if (my $userinfo = $url->userinfo) {
161 0         0 $userinfo =~ s!:.*!:******!;
162 0         0 $url->userinfo($userinfo);
163             }
164              
165 0         0 return $url->query({g => $c->{group}});
166             }
167              
168             sub _dequeue {
169 0     0   0 my ($self, $c) = @_;
170 0         0 my $loop = $self->_loop($c->{nb});
171 0 0       0 my $stream = $loop->stream($c->{id}) or return $self; # stream is not yet connected
172 0         0 my $queue = $c->{queue};
173 0         0 my $buf;
174              
175 0 0       0 if (!$queue->[0]) {
176 0         0 return $self;
177             }
178              
179             # Make sure connection has not been corrupted while event loop was stopped
180 0 0 0     0 if (!$loop->is_running and $stream->is_readable) {
181 0         0 $stream->close;
182 0         0 return $self;
183             }
184              
185 0         0 push @{$c->{waiting}}, shift @$queue;
  0         0  
186 0         0 $buf = $self->_op_to_command($c);
187 0         0 do { local $_ = $buf; s!\r\n!\\r\\n!g; warn "[$c->{name}] <<< ($_)\n" } if DEBUG;
188 0         0 $stream->write($buf);
189 0         0 $self;
190             }
191              
192             sub _error {
193 1782     1782   4134 my ($self, $c, $err) = @_;
194 1782   33     8961 my $waiting = $c->{waiting} || $c->{queue};
195              
196 1782         2782 warn "[$c->{name}] !!! @{[$err // 'close']}\n" if DEBUG;
197              
198 1782 50       4544 return if $self->{destroy};
199 1782 50       4682 return $self->_requeue($c)->_connect($c) unless defined $err;
200 1782 50       4519 return $self->emit(error => $err) unless @$waiting;
201 1782         3774 $self->$_($err, undef) for grep {$_} map { $_->[0] } @$waiting;
  1782         7083  
  1782         5167  
202             }
203              
204             sub _execute {
205 1784 100   1784   6967 my $cb = ref $_[-1] eq 'CODE' ? pop : undef;
206 1784         5940 my ($self, $group, @cmd) = @_;
207              
208 1784 50 66     20294 $self->_cleanup unless ($self->{pid} //= $$) eq $$; # TODO: Fork safety
209              
210 1784 100       5284 if ($cb) {
211 2   50     20 my $c = $self->{connections}{$group} ||= {nb => 1, group => $group};
212 2         4 push @{$c->{queue}}, [$cb, @cmd];
  2         8  
213 2 50       11 return $self->_connect($c) unless $c->{id};
214 0         0 return $self->_dequeue($c);
215             }
216             else {
217 1782   50     8044 my $c = $self->{connections}{$self->_blocking_group} ||= {nb => 0, group => $self->_blocking_group};
218 1782         4158 my ($err, $res);
219              
220 1782     1782   2961 push @{$c->{queue}}, [sub { shift->_loop(0)->stop; ($err, $res) = @_; }, @cmd];
  1782         15873  
  1782         5138  
  1782         25698  
221 1782 50       9188 $c->{id} ? $self->_dequeue($c) : $self->_connect($c);
222 1782         5011 $self->_loop(0)->start;
223 1782 50       236318 die "[@cmd] $err" if $err;
224 0         0 return $res;
225             }
226             }
227              
228             sub _loop {
229 7136 100 66 7136   44078 $_[1] ? Mojo::IOLoop->singleton : ($_[0]->{ioloop} ||= Mojo::IOLoop->new);
230             }
231              
232             sub _op_to_command {
233 0     0   0 my ($self, $c) = @_;
234 0         0 my $op = $c->{waiting}[-1];
235 0         0 my ($i, @data);
236              
237 0         0 for my $token (@$op) {
238 0 0       0 next unless $i++;
239 0 0       0 $token = Mojo::Util::encode($self->encoding, $token) if $self->encoding;
240 0         0 push @data, {type => '$', data => $token};
241             }
242              
243 0         0 $c->{protocol}->encode({type => '*', data => \@data});
244             }
245              
246             sub _pubsub {
247 1 50   1   8 my $cb = ref $_[-1] eq 'CODE' ? pop : sub { };
        1      
248 1         4 my ($self, $op) = (shift, shift);
249 1 50       4 my $channels = ref $_[0] eq 'ARRAY' ? shift : [];
250              
251 1 50       5 unless (@$channels) {
252 0         0 my $method = lc $op;
253 0         0 $channels = [@_];
254 0         0 Mojo::Util::deprecated("$method(\@list, ...) is DEPRECATED: Requires an array-ref as first argument.");
255             }
256              
257 1         4 $self->_execute(pubsub => $op => @$channels, $cb);
258             }
259              
260             sub _read {
261 2     2   35 my ($self, $c, $buf) = @_;
262 2         4 my $protocol = $c->{protocol};
263 2         4 my $event;
264              
265 2         4 do { local $_ = $buf; s!\r\n!\\r\\n!g; warn "[$c->{name}] >>> ($_)\n" } if DEBUG;
266 2         22 $protocol->parse($buf);
267              
268             MESSAGE:
269 1         68 while (my $message = $protocol->get_message) {
270 0         0 my $data = $self->_reencode_message($message);
271              
272 0 0 0     0 if (ref $data eq 'SCALAR') {
    0 0        
273 0   0     0 my $cb = (shift @{$c->{waiting}} || [])->[0];
274 0 0       0 $self->$cb($$data, []) if $cb;
275             }
276             elsif (ref $data eq 'ARRAY' and $data->[0] and $data->[0] =~ /^(p?message)$/i) {
277 0         0 $event = shift @$data;
278 0         0 $self->emit($event => reverse @$data);
279             }
280             else {
281 0   0     0 my $cb = (shift @{$c->{waiting}} || [])->[0];
282 0 0       0 $self->$cb('', $data) if $cb;
283             }
284              
285 0         0 $self->_dequeue($c);
286             }
287             }
288              
289             sub _reencode_message {
290 0     0   0 my ($self, $message) = @_;
291 0         0 my ($type, $data) = @{$message}{qw( type data )};
  0         0  
292              
293 0 0 0     0 if ($type ne '*' and $self->encoding and $data) {
      0        
294 0         0 $data = Encode::decode($self->encoding, $data);
295             }
296              
297 0 0       0 if ($type eq '-') {
    0          
298 0         0 return \$data;
299             }
300             elsif ($type ne '*') {
301 0         0 return $data;
302             }
303             else {
304 0         0 return [map { $self->_reencode_message($_); } @$data];
  0         0  
305             }
306             }
307              
308             sub _requeue {
309 0     0   0 my ($self, $c) = @_;
310              
311 0 0       0 unshift @{$c->{queue}}, grep { $_->[0] } @{delete $c->{waiting} || []};
  0         0  
  0         0  
  0         0  
312 0         0 return $self;
313             }
314              
315 32     32   139 sub _scan_operations { qw(scan sscan hscan zscan); }
316              
317             for my $method (__PACKAGE__->_basic_operations) {
318             my $op = uc $method;
319 0     0 0 0 eval "sub $method { shift->_execute(basic => $op => \@_); }; 1" or die $@;
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  1     1 0 46  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  1782     1782 0 11078  
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
320             }
321              
322             for my $method (__PACKAGE__->_scan_operations) {
323             my $op = uc $method;
324             Mojo::Util::monkey_patch(__PACKAGE__,
325             $method,
326             sub {
327 0     0     my $self = shift;
        0      
        0      
        0      
328 0           return Mojo::Redis2::Cursor->new(command => [$op => @_])->redis($self);
329             }
330             );
331             }
332              
333             1;
334              
335             =encoding utf8
336              
337             =head1 NAME
338              
339             Mojo::Redis2 - (DEPRECATED) Pure-Perl non-blocking I/O Redis driver
340              
341             =head1 VERSION
342              
343             0.36
344              
345             =head1 DEPRECATED
346              
347             Instead of using this module, you should use L instead. Because:
348              
349             =over 2
350              
351             =item *
352              
353             It has a connection pool, meaning you don't have to connect all the time.
354              
355             =item *
356              
357             L follows the same API as L.
358              
359             =item *
360              
361             The blocking API is explicit and use another instance of L.
362              
363             =item *
364              
365             Has support for L.
366              
367             =item *
368              
369             Provides an easy way for caching complex data structures.
370              
371             =item *
372              
373             Not confusing if you use BLPOP (or friends) or pubsub commands, since it's
374             always a different connection.
375              
376             =back
377              
378             =head1 DESCRIPTION
379              
380             L is a pure-Perl non-blocking I/O L
381             driver for the L real-time framework.
382              
383             L has not been maintained for a while, and it has some design
384             flaws that makes it hard to work with. All of this and more is taken care of in
385             L.
386              
387             Want to take over L? Contact me on github and I'll let you have it.
388              
389             I encourage everyone to have a look at L, and I discourage any new
390             codebase from using L.
391              
392             =over 2
393              
394             =item * L
395              
396             =item * L
397              
398             =back
399              
400             =head1 SYNOPSIS
401              
402             I decided to remove the L since I want people to use L
403             instead.
404              
405             See L for more details.
406              
407             =head1 EVENTS
408              
409             =head2 connection
410              
411             $self->on(connection => sub { my ($self, $info) = @_; ... });
412              
413             Emitted when a new connection has been established. C<$info> is a hash ref
414             with:
415              
416             {
417             group => $str, # basic, blocking, blpop, brpop, brpoplpush, publish, ...
418             id => $connection_id,
419             nb => $bool, # blocking/non-blocking
420             }
421              
422             Note: The structure of C<$info> is EXPERIMENTAL.
423              
424             =head2 error
425              
426             $self->on(error => sub { my ($self, $err) = @_; ... });
427              
428             Emitted if an error occurs that can't be associated with an operation.
429              
430             =head2 message
431              
432             $self->on(message => sub {
433             my ($self, $message, $channel) = @_;
434             });
435              
436             Emitted when a C<$message> is received on a C<$channel> after it has been
437             L to.
438              
439             =head2 pmessage
440              
441             $self->on(pmessage => sub {
442             my ($self, $message, $channel, $pattern) = @_;
443             });
444              
445             Emitted when a C<$message> is received on a C<$channel> matching a
446             C<$pattern>, after it has been L to.
447              
448             =head1 ATTRIBUTES
449              
450             =head2 encoding
451              
452             $str = $self->encoding;
453             $self = $self->encoding('UTF-8');
454              
455             Holds the character encoding to use for data from/to Redis. Default is
456             C. Set to C to disable encoding/decoding data. Without an
457             encoding set, Redis expects and returns bytes.
458              
459             =head2 protocol
460              
461             DEPRECATED! The protocol object cannot be shared in high load
462             environments.
463              
464             =head2 protocol_class
465              
466             $str = $self->protocol_class;
467             $self = $self->protocol_class('Protocol::Redis::XS');
468              
469             Holds the class name used to parse/generate Redis messages.
470             Defaults to L or L.
471              
472             L need to be installed manually.
473              
474             =head2 url
475              
476             $url = $self->url;
477              
478             Holds a L object with the location to the Redis server. Default
479             is C or "redis://localhost:6379". The L need to be set
480             in constructor. Examples:
481              
482             Mojo::Redis2->new(url => "redis://x:$auth_key\@$server:$port/$database_index");
483             Mojo::Redis2->new(url => "redis://10.0.0.42:6379");
484             Mojo::Redis2->new(url => "redis://10.0.0.42:6379/1");
485             Mojo::Redis2->new(url => "redis://x:s3cret\@10.0.0.42:6379/1");
486              
487             =head1 METHODS
488              
489             In addition to the methods listed in this module, you can call these Redis
490             methods on C<$self>:
491              
492             =head3 Connection
493              
494             echo, ping
495              
496             =head3 Geo
497              
498             geoadd, geodist, geohash, geopos, georadius,
499             georadiusbymember
500              
501             =head3 Hashes
502              
503             hdel, hexists, hget, hgetall, hincrby, hincrbyfloat,
504             hkeys, hlen, hmget, hmset, hset, hsetnx, hstrlen, hvals
505              
506             =head3 HyperLogLog
507              
508             pfadd, pfcount, pfmerge
509              
510             =head3 Keys
511              
512             del, exists, expire, expireat, keys, move, persist,
513             pexpire, pexpireat, pttl, randomkey, rename, renamenx,
514             sort, ttl, type
515              
516             =head3 Lists
517              
518             lindex, linsert, llen, lpop, lpush, lpushx, lrange, lrem,
519             lset, ltrim, rpop, rpoplpush, rpush, rpushx
520              
521             =head3 PubSub
522              
523             publish
524              
525             =head3 Scripting
526              
527             eval, evalsha
528              
529             =head3 Sets
530              
531             sadd, scard, sdiff, sdiffstore, sinter, sinterstore,
532             sismember, smembers, smove, spop, srandmember, srem,
533             sunion, sunionstore
534              
535             =head3 Sorted Sets
536              
537             zadd, zcard, zcount, zincrby, zinterstore, zlexcount,
538             zrange, zrangebylex, zrangebyscore, zrank, zrem,
539             zremrangebylex, zremrangebyrank, zremrangebyscore,
540             zrevrange, zrevrangebylex, zrevrangebyscore,
541             zrevrank, zscore, zunionstore
542              
543             =head3 Strings
544              
545             append, bitcount, bitop, bitpos, decr, decrby, get,
546             getbit, getrange, getset, incr, incrby, incrbyfloat,
547             mget, mset, msetnx, psetex, set, setbit, setex, setnx,
548             setrange, strlen
549              
550              
551             See L for details.
552              
553             =head2 new
554              
555             $self = Mojo::Redis2->new(...);
556              
557             Object constructor. Makes sure L is an object.
558              
559             =head2 blpop
560              
561             $self = $self->blpop(@keys, $timeout, sub { my ($self, $err, $res) = @_; });
562              
563             This method will issue the BLPOP command on the Redis server, but in its
564             own connection. This means that C<$self> can still be used to run other
565             L instead of being blocking.
566              
567             Note: This method will only work in a non-blocking environment.
568              
569             See also L.
570              
571             =head2 brpop
572              
573             $self = $self->brpop(@keys, $timeout, sub { my ($self, $err, $res) = @_; });
574              
575             Follows the same API as L.
576             See also L.
577              
578             =head2 brpoplpush
579              
580             $self = $self->brpoplpush($from => $to, $timeout, sub { my ($self, $err, $res) = @_; });
581              
582             Follows the same API as L.
583             See also L.
584              
585             =head2 bulk
586              
587             $obj = $self->bulk;
588              
589             Returns a L object which can be used to group Redis
590             operations.
591              
592             =head2 client
593              
594             $self->client->$method(@args);
595              
596             Run "CLIENT" commands using L.
597              
598             =head2 backend
599              
600             $self->backend->$method(@args);
601              
602             Run server commands (CONFIG, INFO, SAVE, ...) using L.
603              
604             =head2 multi
605              
606             $txn = $self->multi;
607              
608             This method does not perform the "MULTI" Redis command, but returns a
609             L object instead.
610              
611             The L object is a subclass of L,
612             which will run all the Redis commands inside a transaction.
613              
614             =head2 psubscribe
615              
616             $self = $self->psubscribe(\@patterns, sub { my ($self, $err, $res) = @_; ... });
617              
618             Used to subscribe to channels that match C<@patterns>. Messages arriving over a
619             matching channel name will result in L events.
620              
621             See L for details.
622              
623             =head2 punsubscribe
624              
625             $self = $self->punsubscribe(\@patterns, sub { my ($self, $err, $res) = @_; ... });
626              
627             The reverse of L.
628             See L for details.
629              
630             =head2 scan, hscan, sscan, zscan
631              
632             $cur = $self->scan(0, MATCH => 'namesoace*', COUNT => 15);
633             $cur = $self->hscan('hash.key', 0, MATCH => 'pref.*');
634             $cur = $self->sscan('set.key', 0);
635             $cur = $self->zscan('zset.key', 0);
636              
637             $res = $cur->next();
638              
639             Methods from C family will return L object to
640             iterate over elements collection.
641              
642             =head2 subscribe
643              
644             $self = $self->subscribe(\@channels, sub { my ($self, $err, $res) = @_; ... });
645              
646             Used to subscribe to C<@channels>. Messages arriving over a channel will
647             result in L events.
648              
649             See L for details.
650              
651             =head2 unsubscribe
652              
653             $self = $self->unsubscribe(\@channels, sub { my ($self, $err, $res) = @_; ... });
654             $self = $self->unsubscribe($event);
655             $self = $self->unsubscribe($event, $cb);
656              
657             The reverse of L. It will also call L
658             unless the first argument is an array-ref of C<@channels>.
659              
660             See L for details.
661              
662             =head1 COPYRIGHT AND LICENSE
663              
664             Copyright (C) 2014, Jan Henning Thorsen
665              
666             This program is free software, you can redistribute it and/or modify it under
667             the terms of the Artistic License version 2.0.
668              
669             =head1 AUTHOR
670              
671             Andre Parker
672              
673             Ben Tyler - C
674              
675             Jan Henning Thorsen - C
676              
677             Mike Magowan - C
678              
679             =cut