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 34     34   3368171 use Mojo::Base 'Mojo::EventEmitter';
  34         101069  
  34         148  
3              
4 34     34   45196 use Mojo::IOLoop;
  34         2880189  
  34         244  
5 34     34   13230 use Mojo::Redis2::Cursor;
  34         74  
  34         211  
6 34     34   10061 use Mojo::Redis2::Server;
  34         76  
  34         207  
7 34     34   13538 use Mojo::URL;
  34         186321  
  34         218  
8 34     34   1013 use Mojo::Util;
  34         62  
  34         871  
9 34     34   152 use Carp ();
  34         116  
  34         770  
10 34   50 34   144 use constant DEBUG => $ENV{MOJO_REDIS_DEBUG} || 0;
  34         56  
  34         2076  
11 34     34   148 use constant DEFAULT_PORT => 6379;
  34         57  
  34         94628  
12              
13             our $VERSION = '0.34';
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 1892   100 1892 1 10064 sub url { $_[0]->{url} ||= Mojo::URL->new($ENV{MOJO_REDIS_URL} || 'redis://localhost:6379'); }
      66        
32              
33             sub new {
34 1890     1890 1 14837 my $self = shift->SUPER::new(@_);
35              
36 1890         21895 $self->{name} = Mojo::Util::steady_time if DEBUG;
37              
38 1890 100 66     14056 if ($self->{url} and ref $self->{url} eq '') {
39 1885 100       14054 $self->{url} = "redis://$self->{url}" unless $self->{url} =~ /^redis:/;
40 1885         14158 $self->{url} = Mojo::URL->new($self->{url});
41             }
42              
43 1890         377850 $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 10 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 1888     1888   8650 sub DESTROY { $_[0]->{destroy} = 1; $_[0]->_cleanup; }
  1888         6263  
86              
87             sub _basic_operations {
88 34     34   401 '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 3762     3762   18926 sub _blocking_group {'blocking'}
103              
104             sub _cleanup {
105 1888     1888   3431 my $self = shift;
106 1888         3716 my $connections = delete $self->{connections};
107              
108 1888         3976 delete $self->{pid};
109              
110 1888         5744 for my $c (values %$connections) {
111 1883 50       4555 my $loop = $self->_loop($c->{nb}) or next;
112 1883 100       4906 $loop->remove($c->{id}) if $c->{id};
113 1883         3337 $self->$_('Premature connection close', []) for grep {$_} map { $_->[0] } @{$c->{waiting}};
  2         6  
  2         4  
  1883         34514  
114             }
115             }
116              
117             sub _connect {
118 1887     1887   4778 my ($self, $c) = @_;
119 1887         5672 my $url = $self->url;
120 1887         13951 my $db = $url->path->[0];
121 1887   100     124303 my @userinfo = split /:/, +($url->userinfo // '');
122              
123 1887         19669 Scalar::Util::weaken($self);
124 1887         6991 $c->{protocol} = $self->protocol_class->new(api => 1);
125 1887         58634 $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 1885     1885   1934301 my ($loop, $err, $stream) = @_;
130              
131 1885 100       5784 if ($err) {
132 1881         4020 delete $c->{id};
133 1881         6685 return $self->_error($c, $err);
134             }
135              
136 4         4 warn "[$c->{name}] --- @{[$self->_debug_url($url, $c)]}\n" if DEBUG;
137              
138 4         10 $stream->timeout(0);
139 4 0       92 $stream->on(close => sub { $self and $self->_error($c) });
  0         0  
140 4 0       30 $stream->on(error => sub { $self and $self->_error($c, $_[1]) });
  0         0  
141 4 0       25 $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       17 unshift @{$c->{queue}}, [undef, SELECT => $db] if $db;
  2         6  
145 4 100       11 unshift @{$c->{queue}}, [undef, AUTH => $userinfo[1]] if length $userinfo[1];
  1         3  
146              
147 4         6 $self->emit(connection => {map { $_ => $c->{$_} } qw( group id nb )});
  12         31  
148 4         36 $self->_dequeue($c);
149             },
150 1887   100     6624 );
151              
152 1887         511468 $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 1881     1881   4181 my ($self, $c, $err) = @_;
194 1881   33     10013 my $waiting = $c->{waiting} || $c->{queue};
195              
196 1881         2579 warn "[$c->{name}] !!! @{[$err // 'close']}\n" if DEBUG;
197              
198 1881 50       4856 return if $self->{destroy};
199 1881 50       4443 return $self->_requeue($c)->_connect($c) unless defined $err;
200 1881 50       4116 return $self->emit(error => $err) unless @$waiting;
201 1881         3598 $self->$_($err, undef) for grep {$_} map { $_->[0] } @$waiting;
  1881         6526  
  1881         4626  
202             }
203              
204             sub _execute {
205 1883 100   1883   7796 my $cb = ref $_[-1] eq 'CODE' ? pop : undef;
206 1883         5859 my ($self, $group, @cmd) = @_;
207              
208 1883 50 66     16417 $self->_cleanup unless ($self->{pid} //= $$) eq $$; # TODO: Fork safety
209              
210 1883 100       4812 if ($cb) {
211 2   50     13 my $c = $self->{connections}{$group} ||= {nb => 1, group => $group};
212 2         3 push @{$c->{queue}}, [$cb, @cmd];
  2         6  
213 2 50       7 return $self->_connect($c) unless $c->{id};
214 0         0 return $self->_dequeue($c);
215             }
216             else {
217 1881   50     8468 my $c = $self->{connections}{$self->_blocking_group} ||= {nb => 0, group => $self->_blocking_group};
218 1881         4032 my ($err, $res);
219              
220 1881     1881   2848 push @{$c->{queue}}, [sub { shift->_loop(0)->stop; ($err, $res) = @_; }, @cmd];
  1881         16164  
  1881         4705  
  1881         23613  
221 1881 50       9763 $c->{id} ? $self->_dequeue($c) : $self->_connect($c);
222 1881         4646 $self->_loop(0)->start;
223 1881 50       199857 die "[@cmd] $err" if $err;
224 0         0 return $res;
225             }
226             }
227              
228             sub _loop {
229 7532 100 66 7532   39852 $_[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   7 my $cb = ref $_[-1] eq 'CODE' ? pop : sub { };
        1      
248 1         3 my ($self, $op) = (shift, shift);
249 1 50       3 my $channels = ref $_[0] eq 'ARRAY' ? shift : [];
250              
251 1 50       3 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         3 $self->_execute(pubsub => $op => @$channels, $cb);
258             }
259              
260             sub _read {
261 2     2   23 my ($self, $c, $buf) = @_;
262 2         3 my $protocol = $c->{protocol};
263 2         2 my $event;
264              
265 2         2 do { local $_ = $buf; s!\r\n!\\r\\n!g; warn "[$c->{name}] >>> ($_)\n" } if DEBUG;
266 2         9 $protocol->parse($buf);
267              
268             MESSAGE:
269 1         43 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 34     34   135 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 27  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  1881     1881 0 11744  
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  0     0 0    
  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 - Pure-Perl non-blocking I/O Redis driver
340              
341             =head1 VERSION
342              
343             0.34
344              
345             =head1 DESCRIPTION
346              
347             L is a pure-Perl non-blocking I/O L
348             driver for the L real-time framework.
349              
350             L has not been maintained for a while, and it has some design
351             flaws that makes it hard to work with. All of this and more is taken care of in
352             L.
353              
354             Want to take over L? Contact me on github and I'll let you have it.
355              
356             I encourage everyone to have a look at L, and I discourage any new
357             codebase from using L.
358              
359             =over 2
360              
361             =item * L
362              
363             =item * L
364              
365             =back
366              
367             =head1 SYNOPSIS
368              
369             =head2 Blocking
370              
371             use Mojo::Redis2;
372             my $redis = Mojo::Redis2->new;
373              
374             # Will die() on error.
375             $res = $redis->set(foo => "42"); # $res = OK
376             $res = $redis->get("foo"); # $res = 42
377              
378             =head2 Non-blocking
379              
380             Mojo::IOLoop->delay(
381             sub {
382             my ($delay) = @_;
383             $redis->ping($delay->begin)->get("foo", $delay->begin);
384             },
385             sub {
386             my ($delay, $ping_err, $ping, $get_err, $get) = @_;
387             # On error: $ping_err and $get_err is set to a string
388             # On success: $ping = "PONG", $get = "42";
389             },
390             );
391              
392             =head2 Pub/sub
393              
394             L can L and re-use the same object to C or
395             run other Redis commands, since it can keep track of multiple connections to
396             the same Redis server. It will also re-use the same connection when you
397             (p)subscribe multiple times.
398              
399             $self->on(message => sub {
400             my ($self, $message, $channel) = @_;
401             });
402              
403             $self->subscribe(["some:channel"], sub {
404             my ($self, $err) = @_;
405              
406             return $self->publish("myapp:errors" => $err) if $err;
407             return $self->incr("subscribed:to:some:channel");
408             });
409              
410             =head2 Mojolicious app
411              
412             use Mojolicious::Lite;
413              
414             helper redis => sub { shift->stash->{redis} ||= Mojo::Redis2->new; };
415              
416             get '/' => sub {
417             my $c = shift;
418              
419             my $tx = $c->render_later->tx;
420             $c->redis->get('some:message', sub {
421             my ($redis, $err, $message) = @_;
422             $c->render(json => { error => $err, message => $message });
423             undef $tx;
424             });
425             };
426              
427             app->start;
428              
429             =head2 Error handling
430              
431             C<$err> in this document is a string containing an error message or
432             empty string on success.
433              
434             =head1 EVENTS
435              
436             =head2 connection
437              
438             $self->on(connection => sub { my ($self, $info) = @_; ... });
439              
440             Emitted when a new connection has been established. C<$info> is a hash ref
441             with:
442              
443             {
444             group => $str, # basic, blocking, blpop, brpop, brpoplpush, publish, ...
445             id => $connection_id,
446             nb => $bool, # blocking/non-blocking
447             }
448              
449             Note: The structure of C<$info> is EXPERIMENTAL.
450              
451             =head2 error
452              
453             $self->on(error => sub { my ($self, $err) = @_; ... });
454              
455             Emitted if an error occurs that can't be associated with an operation.
456              
457             =head2 message
458              
459             $self->on(message => sub {
460             my ($self, $message, $channel) = @_;
461             });
462              
463             Emitted when a C<$message> is received on a C<$channel> after it has been
464             L to.
465              
466             =head2 pmessage
467              
468             $self->on(pmessage => sub {
469             my ($self, $message, $channel, $pattern) = @_;
470             });
471              
472             Emitted when a C<$message> is received on a C<$channel> matching a
473             C<$pattern>, after it has been L to.
474              
475             =head1 ATTRIBUTES
476              
477             =head2 encoding
478              
479             $str = $self->encoding;
480             $self = $self->encoding('UTF-8');
481              
482             Holds the character encoding to use for data from/to Redis. Default is
483             C. Set to C to disable encoding/decoding data. Without an
484             encoding set, Redis expects and returns bytes.
485              
486             =head2 protocol
487              
488             DEPRECATED! The protocol object cannot be shared in high load
489             environments.
490              
491             =head2 protocol_class
492              
493             $str = $self->protocol_class;
494             $self = $self->protocol_class('Protocol::Redis::XS');
495              
496             Holds the class name used to parse/generate Redis messages.
497             Defaults to L or L.
498              
499             L need to be installed manually.
500              
501             =head2 url
502              
503             $url = $self->url;
504              
505             Holds a L object with the location to the Redis server. Default
506             is C or "redis://localhost:6379". The L need to be set
507             in constructor. Examples:
508              
509             Mojo::Redis2->new(url => "redis://x:$auth_key\@$server:$port/$database_index");
510             Mojo::Redis2->new(url => "redis://10.0.0.42:6379");
511             Mojo::Redis2->new(url => "redis://10.0.0.42:6379/1");
512             Mojo::Redis2->new(url => "redis://x:s3cret\@10.0.0.42:6379/1");
513              
514             =head1 METHODS
515              
516             In addition to the methods listed in this module, you can call these Redis
517             methods on C<$self>:
518              
519             =head3 Connection
520              
521             echo, ping
522              
523             =head3 Geo
524              
525             geoadd, geodist, geohash, geopos, georadius,
526             georadiusbymember
527              
528             =head3 Hashes
529              
530             hdel, hexists, hget, hgetall, hincrby, hincrbyfloat,
531             hkeys, hlen, hmget, hmset, hset, hsetnx, hstrlen, hvals
532              
533             =head3 HyperLogLog
534              
535             pfadd, pfcount, pfmerge
536              
537             =head3 Keys
538              
539             del, exists, expire, expireat, keys, move, persist,
540             pexpire, pexpireat, pttl, randomkey, rename, renamenx,
541             sort, ttl, type
542              
543             =head3 Lists
544              
545             lindex, linsert, llen, lpop, lpush, lpushx, lrange, lrem,
546             lset, ltrim, rpop, rpoplpush, rpush, rpushx
547              
548             =head3 PubSub
549              
550             publish
551              
552             =head3 Scripting
553              
554             eval, evalsha
555              
556             =head3 Sets
557              
558             sadd, scard, sdiff, sdiffstore, sinter, sinterstore,
559             sismember, smembers, smove, spop, srandmember, srem,
560             sunion, sunionstore
561              
562             =head3 Sorted Sets
563              
564             zadd, zcard, zcount, zincrby, zinterstore, zlexcount,
565             zrange, zrangebylex, zrangebyscore, zrank, zrem,
566             zremrangebylex, zremrangebyrank, zremrangebyscore,
567             zrevrange, zrevrangebylex, zrevrangebyscore,
568             zrevrank, zscore, zunionstore
569              
570             =head3 Strings
571              
572             append, bitcount, bitop, bitpos, decr, decrby, get,
573             getbit, getrange, getset, incr, incrby, incrbyfloat,
574             mget, mset, msetnx, psetex, set, setbit, setex, setnx,
575             setrange, strlen
576              
577              
578             See L for details.
579              
580             =head2 new
581              
582             $self = Mojo::Redis2->new(...);
583              
584             Object constructor. Makes sure L is an object.
585              
586             =head2 blpop
587              
588             $self = $self->blpop(@keys, $timeout, sub { my ($self, $err, $res) = @_; });
589              
590             This method will issue the BLPOP command on the Redis server, but in its
591             own connection. This means that C<$self> can still be used to run other
592             L instead of being blocking.
593              
594             Note: This method will only work in a non-blocking environment.
595              
596             See also L.
597              
598             =head2 brpop
599              
600             $self = $self->brpop(@keys, $timeout, sub { my ($self, $err, $res) = @_; });
601              
602             Follows the same API as L.
603             See also L.
604              
605             =head2 brpoplpush
606              
607             $self = $self->brpoplpush($from => $to, $timeout, sub { my ($self, $err, $res) = @_; });
608              
609             Follows the same API as L.
610             See also L.
611              
612             =head2 bulk
613              
614             $obj = $self->bulk;
615              
616             Returns a L object which can be used to group Redis
617             operations.
618              
619             =head2 client
620              
621             $self->client->$method(@args);
622              
623             Run "CLIENT" commands using L.
624              
625             =head2 backend
626              
627             $self->backend->$method(@args);
628              
629             Run server commands (CONFIG, INFO, SAVE, ...) using L.
630              
631             =head2 multi
632              
633             $txn = $self->multi;
634              
635             This method does not perform the "MULTI" Redis command, but returns a
636             L object instead.
637              
638             The L object is a subclass of L,
639             which will run all the Redis commands inside a transaction.
640              
641             =head2 psubscribe
642              
643             $self = $self->psubscribe(\@patterns, sub { my ($self, $err, $res) = @_; ... });
644              
645             Used to subscribe to channels that match C<@patterns>. Messages arriving over a
646             matching channel name will result in L events.
647              
648             See L for details.
649              
650             =head2 punsubscribe
651              
652             $self = $self->punsubscribe(\@patterns, sub { my ($self, $err, $res) = @_; ... });
653              
654             The reverse of L.
655             See L for details.
656              
657             =head2 scan, hscan, sscan, zscan
658              
659             $cur = $self->scan(0, MATCH => 'namesoace*', COUNT => 15);
660             $cur = $self->hscan('hash.key', 0, MATCH => 'pref.*');
661             $cur = $self->sscan('set.key', 0);
662             $cur = $self->zscan('zset.key', 0);
663              
664             $res = $cur->next();
665              
666             Methods from C family will return L object to
667             iterate over elements collection.
668              
669             =head2 subscribe
670              
671             $self = $self->subscribe(\@channels, sub { my ($self, $err, $res) = @_; ... });
672              
673             Used to subscribe to C<@channels>. Messages arriving over a channel will
674             result in L events.
675              
676             See L for details.
677              
678             =head2 unsubscribe
679              
680             $self = $self->unsubscribe(\@channels, sub { my ($self, $err, $res) = @_; ... });
681             $self = $self->unsubscribe($event);
682             $self = $self->unsubscribe($event, $cb);
683              
684             The reverse of L. It will also call L
685             unless the first argument is an array-ref of C<@channels>.
686              
687             See L for details.
688              
689             =head1 COPYRIGHT AND LICENSE
690              
691             Copyright (C) 2014, Jan Henning Thorsen
692              
693             This program is free software, you can redistribute it and/or modify it under
694             the terms of the Artistic License version 2.0.
695              
696             =head1 AUTHOR
697              
698             Andre Parker
699              
700             Ben Tyler - C
701              
702             Jan Henning Thorsen - C
703              
704             Mike Magowan - C
705              
706             =cut