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 |