redis-namespace 1.9.0 → 1.11.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 88bd88ddb249a9424c8bcc002b84f097a96b4de6450944bc66096e6524115431
4
- data.tar.gz: 1b9b4d59744b77a65ec523a77ea438de1f0923494a838c94a8c312893dce1fa6
3
+ metadata.gz: e003f4015162bfd465e79dd90e54b44ae46f0ec269118e10c08215d639166296
4
+ data.tar.gz: 16078b51e1bdab24977aa2b6fb7d0cd4761a7c41c340fcdacfb96dd32216c061
5
5
  SHA512:
6
- metadata.gz: 2007d2f5396aec757c50d77de437dc01630b10de02eaeb852f7858233729476582036cf8214ba6e893f3e26b574c22169530a44bf9fb24c39fa2f2d5958e7ee5
7
- data.tar.gz: af47dc4b2ce8357f8751c99ed71d05dc213a75a8092a3d54f016cef36b327967445b915bfaed32565639b0b2c16dbd02ef0026fbabcbf07c8965d3bb42b04f16
6
+ metadata.gz: fb965b575fe3ec2f2f45b99a71839f569f647681939b16576c053ab3e25bf85db1db030941bbe6eaeecc624eeeaf8c0497c58c53c4231440896e9e116bc189e3
7
+ data.tar.gz: 07b2b2e20c4a152b3e3a4cfbf6abad773f335e098067a9b213e29dd80cfc4519f3d27c43febe6cf8261ffe95e73184e23a1b9ff557007eb7a8308e43a398bbb1
@@ -2,6 +2,6 @@
2
2
 
3
3
  class Redis
4
4
  class Namespace
5
- VERSION = '1.9.0'
5
+ VERSION = '1.11.0'
6
6
  end
7
7
  end
@@ -72,6 +72,7 @@ class Redis
72
72
  "exists?" => [ :all ],
73
73
  "expire" => [ :first ],
74
74
  "expireat" => [ :first ],
75
+ "expiretime" => [ :first ],
75
76
  "eval" => [ :eval_style ],
76
77
  "evalsha" => [ :eval_style ],
77
78
  "get" => [ :first ],
@@ -122,6 +123,7 @@ class Redis
122
123
  "persist" => [ :first ],
123
124
  "pexpire" => [ :first ],
124
125
  "pexpireat" => [ :first ],
126
+ "pexpiretime" => [ :first ],
125
127
  "pfadd" => [ :first ],
126
128
  "pfcount" => [ :all ],
127
129
  "pfmerge" => [ :all ],
@@ -138,6 +140,7 @@ class Redis
138
140
  "rpush" => [ :first ],
139
141
  "rpushx" => [ :first ],
140
142
  "sadd" => [ :first ],
143
+ "sadd?" => [ :first ],
141
144
  "scard" => [ :first ],
142
145
  "scan" => [ :scan_style, :second ],
143
146
  "scan_each" => [ :scan_style, :all ],
@@ -158,6 +161,7 @@ class Redis
158
161
  "spop" => [ :first ],
159
162
  "srandmember" => [ :first ],
160
163
  "srem" => [ :first ],
164
+ "srem?" => [ :first ],
161
165
  "sscan" => [ :first ],
162
166
  "sscan_each" => [ :first ],
163
167
  "strlen" => [ :first ],
@@ -202,6 +206,7 @@ class Redis
202
206
  HELPER_COMMANDS = {
203
207
  "auth" => [],
204
208
  "disconnect!" => [],
209
+ "close" => [],
205
210
  "echo" => [],
206
211
  "ping" => [],
207
212
  "time" => [],
@@ -238,6 +243,16 @@ class Redis
238
243
  # Support 1.8.7 by providing a namespaced reference to Enumerable::Enumerator
239
244
  Enumerator = Enumerable::Enumerator unless defined?(::Enumerator)
240
245
 
246
+ # This is used by the Redis gem to determine whether or not to display that deprecation message.
247
+ @sadd_returns_boolean = true
248
+
249
+ # This is used by the Redis gem to determine whether or not to display that deprecation message.
250
+ @srem_returns_boolean = true
251
+
252
+ class << self
253
+ attr_accessor :sadd_returns_boolean, :srem_returns_boolean
254
+ end
255
+
241
256
  attr_writer :namespace
242
257
  attr_reader :redis
243
258
  attr_accessor :warning
@@ -329,6 +344,32 @@ class Redis
329
344
  end
330
345
  ruby2_keywords(:eval) if respond_to?(:ruby2_keywords, true)
331
346
 
347
+ # This operation can run for a very long time if the namespace contains lots of keys!
348
+ # It should be used in tests, or when the namespace is small enough
349
+ # and you are sure you know what you are doing.
350
+ def clear
351
+ if warning?
352
+ warn("This operation can run for a very long time if the namespace contains lots of keys! " +
353
+ "It should be used in tests, or when the namespace is small enough " +
354
+ "and you are sure you know what you are doing.")
355
+ end
356
+
357
+ batch_size = 1000
358
+
359
+ if supports_scan?
360
+ cursor = "0"
361
+ begin
362
+ cursor, keys = scan(cursor, count: batch_size)
363
+ del(*keys) unless keys.empty?
364
+ end until cursor == "0"
365
+ else
366
+ all_keys = keys("*")
367
+ all_keys.each_slice(batch_size) do |keys|
368
+ del(*keys)
369
+ end
370
+ end
371
+ end
372
+
332
373
  ADMINISTRATIVE_COMMANDS.keys.each do |command|
333
374
  define_method(command) do |*args, &block|
334
375
  raise NoMethodError if deprecations?
@@ -371,7 +412,8 @@ class Redis
371
412
  "passthrough has been deprecated and will be removed in " +
372
413
  "redis-namespace 2.0 (at #{call_site})")
373
414
  end
374
- @redis.send(command, *args, &block)
415
+
416
+ wrapped_send(@redis, command, args, &block)
375
417
  else
376
418
  super
377
419
  end
@@ -476,7 +518,7 @@ class Redis
476
518
  end
477
519
 
478
520
  # Dispatch the command to Redis and store the result.
479
- result = @redis.send(command, *args, &block)
521
+ result = wrapped_send(@redis, command, args, &block)
480
522
 
481
523
  # Don't try to remove namespace from a Redis::Future, you can't.
482
524
  return result if result.is_a?(Redis::Future)
@@ -513,6 +555,16 @@ class Redis
513
555
  end
514
556
  end
515
557
 
558
+ def wrapped_send(redis_client, command, args = [], &block)
559
+ if redis_client.class.name == "ConnectionPool"
560
+ redis_client.with do |pool_connection|
561
+ pool_connection.send(command, *args, &block)
562
+ end
563
+ else
564
+ redis_client.send(command, *args, &block)
565
+ end
566
+ end
567
+
516
568
  # Avoid modifying the caller's (pass-by-reference) arguments.
517
569
  def clone_args(arg)
518
570
  if arg.is_a?(Array)
@@ -530,13 +582,10 @@ class Redis
530
582
 
531
583
  def namespaced_block(command, &block)
532
584
  if block.arity == 0
533
- redis.send(command, &block)
585
+ wrapped_send(redis, command, &block)
534
586
  else
535
- redis.send(command) do |r|
536
- copy = dup
537
- copy.redis = r
538
- yield copy
539
- end
587
+ outer_block = proc { |r| copy = dup; copy.redis = r; yield copy }
588
+ wrapped_send(redis, command, &outer_block)
540
589
  end
541
590
  end
542
591
 
@@ -582,5 +631,10 @@ class Redis
582
631
  Enumerator.new(&block)
583
632
  end
584
633
  end
634
+
635
+ def supports_scan?
636
+ redis_version = @redis.info["redis_version"]
637
+ Gem::Version.new(redis_version) >= Gem::Version.new("2.8.0")
638
+ end
585
639
  end
586
640
  end
@@ -31,7 +31,7 @@ describe Redis::Namespace do
31
31
  end
32
32
 
33
33
  before(:each) do
34
- allow(redis).to receive(:unhandled) do |*args|
34
+ allow(redis).to receive(:unhandled) do |*args|
35
35
  "unhandled(#{args.inspect})"
36
36
  end
37
37
  allow(redis).to receive(:flushdb).and_return("OK")
data/spec/redis_spec.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require File.dirname(__FILE__) + '/spec_helper'
4
+ require 'connection_pool'
4
5
 
5
6
  describe "redis" do
6
7
  @redis_version = Gem::Version.new(Redis.new.info["redis_version"])
@@ -184,6 +185,24 @@ describe "redis" do
184
185
  expect(@namespaced.mapped_mget('foo', 'baz', 'bar')).to eq({'foo'=>'1000', 'bar'=>'2000', 'baz' => nil})
185
186
  end
186
187
 
188
+ it "should utilize connection_pool while using a namespace with mget" do
189
+ memo = @namespaced
190
+ connection_pool = ConnectionPool.new(size: 2, timeout: 2) { Redis.new db: 15 }
191
+ @namespaced = Redis::Namespace.new(:ns, redis: connection_pool)
192
+
193
+ expect(connection_pool).to receive(:with).and_call_original do |arg|
194
+ expect(arg).to be(an_instance_of(Redis))
195
+ end.at_least(:once)
196
+
197
+ @namespaced.set('foo', 1000)
198
+ @namespaced.set('bar', 2000)
199
+ expect(@namespaced.mapped_mget('foo', 'bar')).to eq({ 'foo' => '1000', 'bar' => '2000' })
200
+ expect(@namespaced.mapped_mget('foo', 'baz', 'bar')).to eq({'foo'=>'1000', 'bar'=>'2000', 'baz' => nil})
201
+ @redis.get('foo').should eq('bar')
202
+
203
+ @namespaced = memo
204
+ end
205
+
187
206
  it "should be able to use a namespace with mset" do
188
207
  @namespaced.mset('foo', '1000', 'bar', '2000')
189
208
  expect(@namespaced.mapped_mget('foo', 'bar')).to eq({ 'foo' => '1000', 'bar' => '2000' })
@@ -339,6 +358,17 @@ describe "redis" do
339
358
  expect(values).to match_array(['banana', 'eggplant'])
340
359
  end
341
360
 
361
+ it "should add a new member" do
362
+ expect(@namespaced.sadd?('foo', 1)).to eq(true)
363
+ expect(@namespaced.sadd?('foo', 1)).to eq(false)
364
+ end
365
+
366
+ it "should remove members" do
367
+ @namespaced.sadd('foo', 1)
368
+ expect(@namespaced.srem?('foo', 1)).to eq(true)
369
+ expect(@namespaced.srem?('foo', 1)).to eq(false)
370
+ end
371
+
342
372
  it "should add namespace to sort" do
343
373
  @namespaced.sadd('foo', 1)
344
374
  @namespaced.sadd('foo', 2)
@@ -376,6 +406,26 @@ describe "redis" do
376
406
  expect(@namespaced.hgetall("foo")).to eq({"key1" => "value1"})
377
407
  end
378
408
 
409
+ it "should utilize connection_pool while adding namepsace to multi blocks" do
410
+ memo = @namespaced
411
+ connection_pool = ConnectionPool.new(size: 2, timeout: 2) { Redis.new db: 15 }
412
+ @namespaced = Redis::Namespace.new(:ns, redis: connection_pool)
413
+
414
+ expect(connection_pool).to receive(:with).and_call_original do |arg|
415
+ expect(arg).to be(an_instance_of(Redis))
416
+ end.at_least(:once)
417
+
418
+ @namespaced.mapped_hmset "foo", {"key" => "value"}
419
+ @namespaced.multi do |r|
420
+ r.del "foo"
421
+ r.mapped_hmset "foo", {"key1" => "value1"}
422
+ end
423
+ expect(@redis.get("foo")).to eq("bar")
424
+ expect(@namespaced.hgetall("foo")).to eq({"key1" => "value1"})
425
+
426
+ @namespaced = memo
427
+ end
428
+
379
429
  it "should pass through multi commands without block" do
380
430
  @namespaced.mapped_hmset "foo", {"key" => "value"}
381
431
 
@@ -387,6 +437,28 @@ describe "redis" do
387
437
  expect(@namespaced.hgetall("foo")).to eq({"key1" => "value1"})
388
438
  end
389
439
 
440
+ it "should utilize connection_pool while passing through multi commands without block" do
441
+ memo = @namespaced
442
+ connection_pool = ConnectionPool.new(size: 2, timeout: 2) { Redis.new db: 15 }
443
+ @namespaced = Redis::Namespace.new(:ns, redis: connection_pool)
444
+
445
+ expect(connection_pool).to receive(:with).and_call_original do |arg|
446
+ expect(arg).to be(an_instance_of(Redis))
447
+ end.at_least(:once)
448
+
449
+ @namespaced.mapped_hmset "foo", {"key" => "value"}
450
+
451
+ @namespaced.multi
452
+ @namespaced.del "foo"
453
+ @namespaced.mapped_hmset "foo", {"key1" => "value1"}
454
+ @namespaced.exec
455
+
456
+ expect(@namespaced.hgetall("foo")).to eq({"key1" => "value1"})
457
+ expect(@redis.get("foo")).to eq("bar")
458
+
459
+ @namespaced = memo
460
+ end
461
+
390
462
  it 'should return futures without attempting to remove namespaces' do
391
463
  @namespaced.multi do
392
464
  @future = @namespaced.keys('*')
@@ -403,6 +475,26 @@ describe "redis" do
403
475
  expect(@namespaced.hgetall("foo")).to eq({"key1" => "value1"})
404
476
  end
405
477
 
478
+ it "should utilize connection_pool while adding namespace to pipelined blocks" do
479
+ memo = @namespaced
480
+ connection_pool = ConnectionPool.new(size: 2, timeout: 2) { Redis.new db: 15 }
481
+ @namespaced = Redis::Namespace.new(:ns, redis: connection_pool)
482
+
483
+ expect(connection_pool).to receive(:with).and_call_original do |arg|
484
+ expect(arg).to be(an_instance_of(Redis))
485
+ end.at_least(:once)
486
+
487
+ @namespaced.mapped_hmset "foo", {"key" => "value"}
488
+ @namespaced.pipelined do |r|
489
+ r.del "foo"
490
+ r.mapped_hmset "foo", {"key1" => "value1"}
491
+ end
492
+ expect(@namespaced.hgetall("foo")).to eq({"key1" => "value1"})
493
+ expect(@redis.get("foo")).to eq("bar")
494
+
495
+ @namespaced = memo
496
+ end
497
+
406
498
  it "should returned response array from pipelined block" do
407
499
  @namespaced.mset "foo", "bar", "key", "value"
408
500
  result = @namespaced.pipelined do |r|
@@ -574,6 +666,12 @@ describe "redis" do
574
666
  expect(@redis.ttl("ns:foo")).to satisfy {|v| (0..1).include?(v) }
575
667
  end
576
668
 
669
+ it "should namespace expiretime" do
670
+ @namespaced.set('mykey', 'Hello')
671
+ @namespaced.expireat('mykey', 2000000000)
672
+ expect(@namespaced.expiretime('mykey')).to eq(2000000000)
673
+ end
674
+
577
675
  it "should namespace hincrbyfloat" do
578
676
  @namespaced.hset('mykey', 'field', 10.50)
579
677
  expect(@namespaced.hincrbyfloat('mykey', 'field', 0.1)).to eq(10.6)
@@ -606,6 +704,12 @@ describe "redis" do
606
704
  expect(@namespaced.pexpire('mykey', 1555555555005)).to eq(true)
607
705
  end
608
706
 
707
+ it "should namespace pexpiretime" do
708
+ @namespaced.set('mykey', 'Hello')
709
+ @namespaced.pexpireat('mykey', 2000000000000)
710
+ expect(@namespaced.pexpiretime('mykey')).to eq(2000000000000)
711
+ end
712
+
609
713
  it "should namespace psetex" do
610
714
  expect(@namespaced.psetex('mykey', 10000, 'Hello')).to eq('OK')
611
715
  expect(@namespaced.get('mykey')).to eq('Hello')
@@ -967,4 +1071,30 @@ describe "redis" do
967
1071
  expect(sub_sub_namespaced.full_namespace).to eql("ns:sub1:sub2")
968
1072
  end
969
1073
  end
1074
+
1075
+ describe :clear do
1076
+ it "warns with helpful output" do
1077
+ expect { @namespaced.clear }.to output(/can run for a very long time/).to_stderr
1078
+ end
1079
+
1080
+ it "should delete all the keys" do
1081
+ @redis.set("foo", "bar")
1082
+ @namespaced.mset("foo1", "bar", "foo2", "bar")
1083
+ capture_stderr { @namespaced.clear }
1084
+
1085
+ expect(@redis.keys).to eq ["foo"]
1086
+ expect(@namespaced.keys).to be_empty
1087
+ end
1088
+
1089
+ it "should delete all the keys in older redis" do
1090
+ allow(@redis).to receive(:info).and_return({ "redis_version" => "2.7.0" })
1091
+
1092
+ @redis.set("foo", "bar")
1093
+ @namespaced.mset("foo1", "bar", "foo2", "bar")
1094
+ capture_stderr { @namespaced.clear }
1095
+
1096
+ expect(@redis.keys).to eq ["foo"]
1097
+ expect(@namespaced.keys).to be_empty
1098
+ end
1099
+ end
970
1100
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis-namespace
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.0
4
+ version: 1.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Wanstrath
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2022-08-13 00:00:00.000000000 Z
15
+ date: 2023-06-08 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: redis
@@ -70,6 +70,20 @@ dependencies:
70
70
  - - ">="
71
71
  - !ruby/object:Gem::Version
72
72
  version: '0'
73
+ - !ruby/object:Gem::Dependency
74
+ name: connection_pool
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ type: :development
81
+ prerelease: false
82
+ version_requirements: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
73
87
  description: |
74
88
  Adds a Redis::Namespace class which can be used to namespace calls
75
89
  to Redis. This is useful when using a single instance of Redis with
@@ -99,8 +113,7 @@ licenses:
99
113
  metadata:
100
114
  bug_tracker_uri: https://github.com/resque/redis-namespace/issues
101
115
  changelog_uri: https://github.com/resque/redis-namespace/blob/master/CHANGELOG.md
102
- documentation_uri: https://www.rubydoc.info/gems/redis-namespace/1.9.0
103
- source_code_uri: https://github.com/resque/redis-namespace/tree/v1.9.0
116
+ documentation_uri: https://www.rubydoc.info/gems/redis-namespace/1.11.0
104
117
  rubygems_mfa_required: 'true'
105
118
  post_install_message:
106
119
  rdoc_options: []
@@ -117,7 +130,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
117
130
  - !ruby/object:Gem::Version
118
131
  version: '0'
119
132
  requirements: []
120
- rubygems_version: 3.1.6
133
+ rubygems_version: 3.4.1
121
134
  signing_key:
122
135
  specification_version: 4
123
136
  summary: Namespaces Redis commands.