redis-namespace 1.5.1 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -13
- data/LICENSE +17 -16
- data/README.md +85 -20
- data/lib/redis/namespace.rb +155 -44
- data/lib/redis/namespace/version.rb +1 -1
- data/spec/deprecation_spec.rb +34 -2
- data/spec/redis_spec.rb +321 -179
- data/spec/spec_helper.rb +5 -0
- metadata +38 -31
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
ZGVlNjU3MDUxNDA3M2I0ZjVlYjQ5ZGJmYmYzOGNiOGJkMjI3NTUwZA==
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 07470c91421a4a15227f10daff0378fdd85a7ba7abc30357677cca67ca87305f
|
4
|
+
data.tar.gz: 50e2b6ff0b1db22abe4bbfd77e486d9fd71c09122ba3c01bbfbf90710d21353d
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
OGYyMmE1M2M1ZDY0MWZmZWIwNDA1NDk5M2VlYTcyZDliMTJmZDBhMGFiYTUx
|
11
|
-
MWMzMjJiYmFhMGE1YjlkMDM2ODY5NzFiNjM1YjQyNDBhMWQzZjc=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
YjY1MGZkZmEzOWNhNmRhMTEzNjQ0MGNkYTQ4YWZmZjQ1YTAwNzA2MmJkZWJl
|
14
|
-
OTQ0MWQ3NWNiMzU1YjNkYzYzZGM4MTAyNGE3NTFkMTk0N2UzN2IyZThjY2Zk
|
15
|
-
NjJhODIyMGY1NzNmNThmN2E2MDUyOWJkNWU1OWZlZjA5MDdmM2I=
|
6
|
+
metadata.gz: ec82e340922480f5a48a8bba472babc3385abc84104b56d13f9e94a2654c5a4aaef1d38f1c2a11535a8f5c5ca02aed3ab1c157fb983b7251458f6b8547b08710
|
7
|
+
data.tar.gz: 129b38893696d94b57aa04d07fe399e59d76fd6b4269531c7dbee9334604041b9a1fca931ff7a4a8e16dee9b57f9756e26a6cf1b3d9f989139dbcd31f6d5b0ce
|
data/LICENSE
CHANGED
@@ -1,20 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
1
3
|
Copyright (c) 2009 Chris Wanstrath
|
2
4
|
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
the following conditions:
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
10
11
|
|
11
|
-
The above copyright notice and this permission notice shall be
|
12
|
-
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
13
14
|
|
14
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
OF
|
20
|
-
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
CHANGED
@@ -1,38 +1,103 @@
|
|
1
1
|
redis-namespace
|
2
|
-
|
2
|
+
===============
|
3
|
+
|
4
|
+
Redis::Namespace provides an interface to a namespaced subset of your [redis][] keyspace (e.g., keys with a common beginning), and requires the [redis-rb][] gem.
|
5
|
+
|
6
|
+
```ruby
|
7
|
+
require 'redis-namespace'
|
8
|
+
# => true
|
9
|
+
|
10
|
+
redis_connection = Redis.new
|
11
|
+
# => #<Redis client v3.1.0 for redis://127.0.0.1:6379/0>
|
12
|
+
namespaced_redis = Redis::Namespace.new(:ns, redis: redis_connection)
|
13
|
+
# => #<Redis::Namespace v1.5.0 with client v3.1.0 for redis://127.0.0.1:6379/0/ns>
|
14
|
+
|
15
|
+
namespaced_redis.set('foo', 'bar') # redis_connection.set('ns:foo', 'bar')
|
16
|
+
# => "OK"
|
17
|
+
|
18
|
+
# Redis::Namespace automatically prepended our namespace to the key
|
19
|
+
# before sending it to our redis client.
|
20
|
+
|
21
|
+
namespaced_redis.get('foo')
|
22
|
+
# => "bar"
|
23
|
+
redis_connection.get('foo')
|
24
|
+
# => nil
|
25
|
+
redis_connection.get('ns:foo')
|
26
|
+
# => "bar"
|
27
|
+
|
28
|
+
namespaced_redis.del('foo')
|
29
|
+
# => 1
|
30
|
+
namespaced_redis.get('foo')
|
31
|
+
# => nil
|
32
|
+
redis_connection.get('ns:foo')
|
33
|
+
# => nil
|
34
|
+
```
|
3
35
|
|
4
|
-
|
36
|
+
Installation
|
37
|
+
============
|
5
38
|
|
6
|
-
|
39
|
+
Redis::Namespace is packaged as the redis-namespace gem, and hosted on rubygems.org.
|
7
40
|
|
8
|
-
|
9
|
-
|
10
|
-
|
41
|
+
From the command line:
|
42
|
+
|
43
|
+
$ gem install redis-namespace
|
44
|
+
|
45
|
+
Or in your Gemfile:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
gem 'redis-namespace'
|
11
49
|
```
|
12
50
|
|
13
|
-
|
51
|
+
Caveats
|
52
|
+
=======
|
14
53
|
|
15
|
-
|
54
|
+
`Redis::Namespace` provides a namespaced interface to `Redis` by keeping an internal registry of the method signatures in `Redis` provided by the [redis-rb][] gem; we keep track of which arguments need the namespace added, and which return values need the namespace removed.
|
16
55
|
|
17
|
-
|
56
|
+
Blind Passthrough
|
57
|
+
-----------------
|
58
|
+
If your version of this gem doesn't know about a particular command, it can't namespace it. Historically, this has meant that Redis::Namespace blindly passes unknown commands on to the underlying redis connection without modification which can lead to surprising effects.
|
18
59
|
|
60
|
+
As of v1.5.0, blind passthrough has been deprecated, and the functionality will be removed entirely in 2.0.
|
19
61
|
|
20
|
-
|
21
|
-
============
|
62
|
+
If you come across a command that is not yet supported, please open an issue on the [issue tracker][] or submit a pull-request.
|
22
63
|
|
23
|
-
|
64
|
+
Administrative Commands
|
65
|
+
-----------------------
|
66
|
+
The effects of some redis commands cannot be limited to a particular namespace (e.g., `FLUSHALL`, which literally truncates all databases in your redis server, regardless of keyspace). Historically, this has meant that Redis::Namespace intentionally passes administrative commands on to the underlying redis connection without modification, which can lead to surprising effects.
|
24
67
|
|
68
|
+
As of v1.6.0, the direct use of administrative commands has been deprecated, and the functionality will be removed entirely in 2.0; while such commands are often useful for testing or administration, their meaning is inherently hidden when placed behind an interface that implies it will namespace everything.
|
25
69
|
|
70
|
+
The prefered way to send an administrative command is on the redis connection itself, which is publicly exposed as `Redis::Namespace#redis`:
|
26
71
|
|
27
|
-
|
28
|
-
|
72
|
+
```ruby
|
73
|
+
namespaced.redis.flushall()
|
74
|
+
# => "OK"
|
75
|
+
```
|
76
|
+
|
77
|
+
2.x Planned Breaking Changes
|
78
|
+
============================
|
29
79
|
|
30
|
-
|
31
|
-
|
80
|
+
As mentioned above, 2.0 will remove blind passthrough and the administrative command passthrough.
|
81
|
+
By default in 1.5+, deprecation warnings are present and enabled;
|
82
|
+
they can be silenced by initializing `Redis::Namespace` with `warnings: false` or by setting the `REDIS_NAMESPACE_QUIET` environment variable.
|
83
|
+
|
84
|
+
Early opt-in
|
85
|
+
------------
|
86
|
+
|
87
|
+
To enable testing against the 2.x interface before its release, in addition to deprecation warnings, early opt-in to these changes can be enabled by initializing `Redis::Namespace` with `deprecations: true` or by setting the `REDIS_NAMESPACE_DEPRECATIONS` environment variable.
|
88
|
+
This should only be done once all warnings have been addressed.
|
89
|
+
|
90
|
+
Authors
|
91
|
+
=======
|
32
92
|
|
93
|
+
While there are many authors who have contributed to this project, the following have done so on an ongoing basis with at least 5 commits:
|
33
94
|
|
34
|
-
|
35
|
-
|
95
|
+
- Chris Wanstrath (@defunkt)
|
96
|
+
- Ryan Biesemeyer (@yaauie)
|
97
|
+
- Steve Klabnik (@steveklabnik)
|
98
|
+
- Terence Lee (@hone)
|
99
|
+
- Eoin Coffey (@ecoffey)
|
36
100
|
|
37
|
-
|
38
|
-
|
101
|
+
[redis]: http://redis.io
|
102
|
+
[redis-rb]: https://github.com/redis/redis-rb
|
103
|
+
[issue tracker]: https://github.com/resque/redis-namespace/issues
|
data/lib/redis/namespace.rb
CHANGED
@@ -3,7 +3,7 @@ require 'redis/namespace/version'
|
|
3
3
|
|
4
4
|
class Redis
|
5
5
|
class Namespace
|
6
|
-
# The following
|
6
|
+
# The following tables define how input parameters and result
|
7
7
|
# values should be modified for the namespace.
|
8
8
|
#
|
9
9
|
# COMMANDS is a hash. Each key is the name of a command and each
|
@@ -53,33 +53,27 @@ class Redis
|
|
53
53
|
# :all
|
54
54
|
# Add the namespace to all elements returned, e.g.
|
55
55
|
# key1 key2 => namespace:key1 namespace:key2
|
56
|
-
|
57
|
-
"append" => [:first],
|
58
|
-
"auth" => [],
|
59
|
-
"bgrewriteaof" => [],
|
60
|
-
"bgsave" => [],
|
56
|
+
NAMESPACED_COMMANDS = {
|
57
|
+
"append" => [ :first ],
|
61
58
|
"bitcount" => [ :first ],
|
62
59
|
"bitop" => [ :exclude_first ],
|
60
|
+
"bitpos" => [ :first ],
|
63
61
|
"blpop" => [ :exclude_last, :first ],
|
64
62
|
"brpop" => [ :exclude_last, :first ],
|
65
63
|
"brpoplpush" => [ :exclude_last ],
|
66
|
-
"
|
67
|
-
"
|
64
|
+
"bzpopmin" => [ :first ],
|
65
|
+
"bzpopmax" => [ :first ],
|
68
66
|
"debug" => [ :exclude_first ],
|
69
67
|
"decr" => [ :first ],
|
70
68
|
"decrby" => [ :first ],
|
71
69
|
"del" => [ :all ],
|
72
|
-
"discard" => [],
|
73
70
|
"dump" => [ :first ],
|
74
|
-
"
|
75
|
-
"exists"
|
71
|
+
"exists" => [ :all ],
|
72
|
+
"exists?" => [ :all ],
|
76
73
|
"expire" => [ :first ],
|
77
74
|
"expireat" => [ :first ],
|
78
75
|
"eval" => [ :eval_style ],
|
79
76
|
"evalsha" => [ :eval_style ],
|
80
|
-
"exec" => [],
|
81
|
-
"flushall" => [],
|
82
|
-
"flushdb" => [],
|
83
77
|
"get" => [ :first ],
|
84
78
|
"getbit" => [ :first ],
|
85
79
|
"getrange" => [ :first ],
|
@@ -102,9 +96,7 @@ class Redis
|
|
102
96
|
"incr" => [ :first ],
|
103
97
|
"incrby" => [ :first ],
|
104
98
|
"incrbyfloat" => [ :first ],
|
105
|
-
"info" => [],
|
106
99
|
"keys" => [ :first, :all ],
|
107
|
-
"lastsave" => [],
|
108
100
|
"lindex" => [ :first ],
|
109
101
|
"linsert" => [ :first ],
|
110
102
|
"llen" => [ :first ],
|
@@ -123,7 +115,6 @@ class Redis
|
|
123
115
|
"mget" => [ :all ],
|
124
116
|
"monitor" => [ :monitor ],
|
125
117
|
"move" => [ :first ],
|
126
|
-
"multi" => [],
|
127
118
|
"mset" => [ :alternate ],
|
128
119
|
"msetnx" => [ :alternate ],
|
129
120
|
"object" => [ :exclude_first ],
|
@@ -133,14 +124,11 @@ class Redis
|
|
133
124
|
"pfadd" => [ :first ],
|
134
125
|
"pfcount" => [ :all ],
|
135
126
|
"pfmerge" => [ :all ],
|
136
|
-
"ping" => [],
|
137
127
|
"psetex" => [ :first ],
|
138
128
|
"psubscribe" => [ :all ],
|
139
129
|
"pttl" => [ :first ],
|
140
130
|
"publish" => [ :first ],
|
141
131
|
"punsubscribe" => [ :all ],
|
142
|
-
"quit" => [],
|
143
|
-
"randomkey" => [],
|
144
132
|
"rename" => [ :all ],
|
145
133
|
"renamenx" => [ :all ],
|
146
134
|
"restore" => [ :first ],
|
@@ -149,24 +137,19 @@ class Redis
|
|
149
137
|
"rpush" => [ :first ],
|
150
138
|
"rpushx" => [ :first ],
|
151
139
|
"sadd" => [ :first ],
|
152
|
-
"save" => [],
|
153
140
|
"scard" => [ :first ],
|
154
141
|
"scan" => [ :scan_style, :second ],
|
155
142
|
"scan_each" => [ :scan_style, :all ],
|
156
|
-
"script" => [],
|
157
143
|
"sdiff" => [ :all ],
|
158
144
|
"sdiffstore" => [ :all ],
|
159
|
-
"select" => [],
|
160
145
|
"set" => [ :first ],
|
161
146
|
"setbit" => [ :first ],
|
162
147
|
"setex" => [ :first ],
|
163
148
|
"setnx" => [ :first ],
|
164
149
|
"setrange" => [ :first ],
|
165
|
-
"shutdown" => [],
|
166
150
|
"sinter" => [ :all ],
|
167
151
|
"sinterstore" => [ :all ],
|
168
152
|
"sismember" => [ :first ],
|
169
|
-
"slaveof" => [],
|
170
153
|
"smembers" => [ :first ],
|
171
154
|
"smove" => [ :exclude_last ],
|
172
155
|
"sort" => [ :sort ],
|
@@ -181,31 +164,75 @@ class Redis
|
|
181
164
|
"sunionstore" => [ :all ],
|
182
165
|
"ttl" => [ :first ],
|
183
166
|
"type" => [ :first ],
|
167
|
+
"unlink" => [ :all ],
|
184
168
|
"unsubscribe" => [ :all ],
|
185
|
-
"unwatch" => [ :all ],
|
186
|
-
"watch" => [ :all ],
|
187
169
|
"zadd" => [ :first ],
|
188
170
|
"zcard" => [ :first ],
|
189
171
|
"zcount" => [ :first ],
|
190
172
|
"zincrby" => [ :first ],
|
191
173
|
"zinterstore" => [ :exclude_options ],
|
174
|
+
"zpopmin" => [ :first ],
|
175
|
+
"zpopmax" => [ :first ],
|
192
176
|
"zrange" => [ :first ],
|
193
177
|
"zrangebyscore" => [ :first ],
|
178
|
+
"zrangebylex" => [ :first ],
|
194
179
|
"zrank" => [ :first ],
|
195
180
|
"zrem" => [ :first ],
|
196
181
|
"zremrangebyrank" => [ :first ],
|
197
182
|
"zremrangebyscore" => [ :first ],
|
183
|
+
"zremrangebylex" => [ :first ],
|
198
184
|
"zrevrange" => [ :first ],
|
199
185
|
"zrevrangebyscore" => [ :first ],
|
186
|
+
"zrevrangebylex" => [ :first ],
|
200
187
|
"zrevrank" => [ :first ],
|
201
188
|
"zscan" => [ :first ],
|
202
189
|
"zscan_each" => [ :first ],
|
203
190
|
"zscore" => [ :first ],
|
204
|
-
"zunionstore" => [ :exclude_options ]
|
205
|
-
|
206
|
-
|
191
|
+
"zunionstore" => [ :exclude_options ]
|
192
|
+
}
|
193
|
+
TRANSACTION_COMMANDS = {
|
194
|
+
"discard" => [],
|
195
|
+
"exec" => [],
|
196
|
+
"multi" => [],
|
197
|
+
"unwatch" => [ :all ],
|
198
|
+
"watch" => [ :all ],
|
199
|
+
}
|
200
|
+
HELPER_COMMANDS = {
|
201
|
+
"auth" => [],
|
202
|
+
"disconnect!" => [],
|
203
|
+
"echo" => [],
|
204
|
+
"ping" => [],
|
205
|
+
"time" => [],
|
206
|
+
}
|
207
|
+
ADMINISTRATIVE_COMMANDS = {
|
208
|
+
"bgrewriteaof" => [],
|
209
|
+
"bgsave" => [],
|
210
|
+
"config" => [],
|
211
|
+
"dbsize" => [],
|
212
|
+
"flushall" => [],
|
213
|
+
"flushdb" => [],
|
214
|
+
"info" => [],
|
215
|
+
"lastsave" => [],
|
216
|
+
"quit" => [],
|
217
|
+
"randomkey" => [],
|
218
|
+
"save" => [],
|
219
|
+
"script" => [],
|
220
|
+
"select" => [],
|
221
|
+
"shutdown" => [],
|
222
|
+
"slaveof" => [],
|
207
223
|
}
|
208
224
|
|
225
|
+
DEPRECATED_COMMANDS = [
|
226
|
+
ADMINISTRATIVE_COMMANDS
|
227
|
+
].compact.reduce(:merge)
|
228
|
+
|
229
|
+
COMMANDS = [
|
230
|
+
NAMESPACED_COMMANDS,
|
231
|
+
TRANSACTION_COMMANDS,
|
232
|
+
HELPER_COMMANDS,
|
233
|
+
ADMINISTRATIVE_COMMANDS,
|
234
|
+
].compact.reduce(:merge)
|
235
|
+
|
209
236
|
# Support 1.8.7 by providing a namespaced reference to Enumerable::Enumerator
|
210
237
|
Enumerator = Enumerable::Enumerator unless defined?(::Enumerator)
|
211
238
|
|
@@ -222,6 +249,7 @@ class Redis
|
|
222
249
|
@deprecations = !!options.fetch(:deprecations) do
|
223
250
|
ENV['REDIS_NAMESPACE_DEPRECATIONS']
|
224
251
|
end
|
252
|
+
@has_new_client_method = @redis.respond_to?(:_client)
|
225
253
|
end
|
226
254
|
|
227
255
|
def deprecations?
|
@@ -233,7 +261,13 @@ class Redis
|
|
233
261
|
end
|
234
262
|
|
235
263
|
def client
|
236
|
-
|
264
|
+
warn("The client method is deprecated as of redis-rb 4.0.0, please use the new _client" +
|
265
|
+
"method instead. Support for the old method will be removed in redis-namespace 2.0.") if @has_new_client_method && deprecations?
|
266
|
+
_client
|
267
|
+
end
|
268
|
+
|
269
|
+
def _client
|
270
|
+
@has_new_client_method ? @redis._client : @redis.client # for redis-4.0.0
|
237
271
|
end
|
238
272
|
|
239
273
|
# Ruby defines a now deprecated type method so we need to override it here
|
@@ -246,7 +280,9 @@ class Redis
|
|
246
280
|
|
247
281
|
# emulate Ruby 1.9+ and keep respond_to_missing? logic together.
|
248
282
|
def respond_to?(command, include_private=false)
|
249
|
-
|
283
|
+
return !deprecations? if DEPRECATED_COMMANDS.include?(command.to_s.downcase)
|
284
|
+
|
285
|
+
respond_to_missing?(command, include_private) or super
|
250
286
|
end
|
251
287
|
|
252
288
|
def keys(query = nil)
|
@@ -274,6 +310,14 @@ class Redis
|
|
274
310
|
@namespace
|
275
311
|
end
|
276
312
|
|
313
|
+
def full_namespace
|
314
|
+
redis.is_a?(Namespace) ? "#{redis.full_namespace}:#{namespace}" : namespace.to_s
|
315
|
+
end
|
316
|
+
|
317
|
+
def connection
|
318
|
+
@redis.connection.tap { |info| info[:namespace] = @namespace }
|
319
|
+
end
|
320
|
+
|
277
321
|
def exec
|
278
322
|
call_with_namespace(:exec)
|
279
323
|
end
|
@@ -281,19 +325,46 @@ class Redis
|
|
281
325
|
def eval(*args)
|
282
326
|
call_with_namespace(:eval, *args)
|
283
327
|
end
|
328
|
+
ruby2_keywords(:eval) if respond_to?(:ruby2_keywords, true)
|
329
|
+
|
330
|
+
ADMINISTRATIVE_COMMANDS.keys.each do |command|
|
331
|
+
define_method(command) do |*args, &block|
|
332
|
+
raise NoMethodError if deprecations?
|
333
|
+
|
334
|
+
if warning?
|
335
|
+
warn("Passing '#{command}' command to redis as is; " +
|
336
|
+
"administrative commands cannot be effectively namespaced " +
|
337
|
+
"and should be called on the redis connection directly; " +
|
338
|
+
"passthrough has been deprecated and will be removed in " +
|
339
|
+
"redis-namespace 2.0 (at #{call_site})"
|
340
|
+
)
|
341
|
+
end
|
342
|
+
call_with_namespace(command, *args, &block)
|
343
|
+
end
|
344
|
+
ruby2_keywords(command) if respond_to?(:ruby2_keywords, true)
|
345
|
+
end
|
346
|
+
|
347
|
+
COMMANDS.keys.each do |command|
|
348
|
+
next if ADMINISTRATIVE_COMMANDS.include?(command)
|
349
|
+
next if method_defined?(command)
|
350
|
+
|
351
|
+
define_method(command) do |*args, &block|
|
352
|
+
call_with_namespace(command, *args, &block)
|
353
|
+
end
|
354
|
+
ruby2_keywords(command) if respond_to?(:ruby2_keywords, true)
|
355
|
+
end
|
284
356
|
|
285
357
|
def method_missing(command, *args, &block)
|
286
358
|
normalized_command = command.to_s.downcase
|
287
359
|
|
288
360
|
if COMMANDS.include?(normalized_command)
|
289
|
-
|
361
|
+
send(normalized_command, *args, &block)
|
290
362
|
elsif @redis.respond_to?(normalized_command) && !deprecations?
|
291
363
|
# blind passthrough is deprecated and will be removed in 2.0
|
292
364
|
# redis-namespace does not know how to handle this command.
|
293
365
|
# Passing it to @redis as is, where redis-namespace shows
|
294
366
|
# a warning message if @warning is set.
|
295
367
|
if warning?
|
296
|
-
call_site = caller.reject { |l| l.start_with?(__FILE__) }.first
|
297
368
|
warn("Passing '#{command}' command to redis as is; blind " +
|
298
369
|
"passthrough has been deprecated and will be removed in " +
|
299
370
|
"redis-namespace 2.0 (at #{call_site})")
|
@@ -303,16 +374,24 @@ class Redis
|
|
303
374
|
super
|
304
375
|
end
|
305
376
|
end
|
377
|
+
ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
|
378
|
+
|
379
|
+
def inspect
|
380
|
+
"<#{self.class.name} v#{VERSION} with client v#{Redis::VERSION} "\
|
381
|
+
"for #{@redis.id}/#{full_namespace}>"
|
382
|
+
end
|
306
383
|
|
307
384
|
def respond_to_missing?(command, include_all=false)
|
308
|
-
|
385
|
+
normalized_command = command.to_s.downcase
|
309
386
|
|
310
|
-
|
311
|
-
|
312
|
-
|
387
|
+
case
|
388
|
+
when COMMANDS.include?(normalized_command)
|
389
|
+
true
|
390
|
+
when !deprecations? && redis.respond_to?(command, include_all)
|
391
|
+
true
|
392
|
+
else
|
393
|
+
defined?(super) && super
|
313
394
|
end
|
314
|
-
|
315
|
-
defined?(super) && super
|
316
395
|
end
|
317
396
|
|
318
397
|
def call_with_namespace(command, *args, &block)
|
@@ -324,10 +403,14 @@ class Redis
|
|
324
403
|
|
325
404
|
(before, after) = handling
|
326
405
|
|
406
|
+
# Modify the local *args array in-place, no need to copy it.
|
407
|
+
args.map! {|arg| clone_args(arg)}
|
408
|
+
|
327
409
|
# Add the namespace to any parameters that are keys.
|
328
410
|
case before
|
329
411
|
when :first
|
330
412
|
args[0] = add_namespace(args[0]) if args[0]
|
413
|
+
args[-1] = ruby2_keywords_hash(args[-1]) if args[-1].is_a?(Hash)
|
331
414
|
when :all
|
332
415
|
args = add_namespace(args)
|
333
416
|
when :exclude_first
|
@@ -340,7 +423,7 @@ class Redis
|
|
340
423
|
args.push(last) if last
|
341
424
|
when :exclude_options
|
342
425
|
if args.last.is_a?(Hash)
|
343
|
-
last = args.pop
|
426
|
+
last = ruby2_keywords_hash(args.pop)
|
344
427
|
args = add_namespace(args)
|
345
428
|
args.push(last)
|
346
429
|
else
|
@@ -360,6 +443,7 @@ class Redis
|
|
360
443
|
args[1][:get].each_index do |i|
|
361
444
|
args[1][:get][i] = add_namespace(args[1][:get][i]) unless args[1][:get][i] == "#"
|
362
445
|
end
|
446
|
+
args[1] = ruby2_keywords_hash(args[1])
|
363
447
|
end
|
364
448
|
when :eval_style
|
365
449
|
# redis.eval() and evalsha() can either take the form:
|
@@ -380,7 +464,7 @@ class Redis
|
|
380
464
|
when :scan_style
|
381
465
|
options = (args.last.kind_of?(Hash) ? args.pop : {})
|
382
466
|
options[:match] = add_namespace(options.fetch(:match, '*'))
|
383
|
-
args << options
|
467
|
+
args << ruby2_keywords_hash(options)
|
384
468
|
|
385
469
|
if block
|
386
470
|
original_block = block
|
@@ -406,9 +490,35 @@ class Redis
|
|
406
490
|
|
407
491
|
result
|
408
492
|
end
|
493
|
+
ruby2_keywords(:call_with_namespace) if respond_to?(:ruby2_keywords, true)
|
409
494
|
|
410
495
|
private
|
411
496
|
|
497
|
+
if Hash.respond_to?(:ruby2_keywords_hash)
|
498
|
+
def ruby2_keywords_hash(kwargs)
|
499
|
+
Hash.ruby2_keywords_hash(kwargs)
|
500
|
+
end
|
501
|
+
else
|
502
|
+
def ruby2_keywords_hash(kwargs)
|
503
|
+
kwargs
|
504
|
+
end
|
505
|
+
end
|
506
|
+
|
507
|
+
# Avoid modifying the caller's (pass-by-reference) arguments.
|
508
|
+
def clone_args(arg)
|
509
|
+
if arg.is_a?(Array)
|
510
|
+
arg.map {|sub_arg| clone_args(sub_arg)}
|
511
|
+
elsif arg.is_a?(Hash)
|
512
|
+
Hash[arg.map {|k, v| [clone_args(k), clone_args(v)]}]
|
513
|
+
else
|
514
|
+
arg # Some objects (e.g. symbol) can't be dup'd.
|
515
|
+
end
|
516
|
+
end
|
517
|
+
|
518
|
+
def call_site
|
519
|
+
caller.reject { |l| l.start_with?(__FILE__) }.first
|
520
|
+
end
|
521
|
+
|
412
522
|
def namespaced_block(command, &block)
|
413
523
|
redis.send(command) do |r|
|
414
524
|
begin
|
@@ -425,9 +535,10 @@ class Redis
|
|
425
535
|
|
426
536
|
case key
|
427
537
|
when Array
|
428
|
-
key.map {|k| add_namespace k}
|
538
|
+
key.map! {|k| add_namespace k}
|
429
539
|
when Hash
|
430
|
-
|
540
|
+
key.keys.each {|k| key[add_namespace(k)] = key.delete(k)}
|
541
|
+
key
|
431
542
|
else
|
432
543
|
"#{@namespace}:#{key}"
|
433
544
|
end
|