redis-objects 1.4.2 → 1.4.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7d42c057174f5a48560f104f08c5cf9bb25bd1772dd0684912a0094c4158840b
4
- data.tar.gz: a0f945a9aede01c5623486576444c370cacd0e8a4fa2315511e7c1245339e489
3
+ metadata.gz: 6a9f86f294c2283b6ceae1730dfe6f1d1c3665ac9733cd107a4aa522d8a66bda
4
+ data.tar.gz: 50d631298aff5bcd5b15179c1a700a56a512c4a096cedad4c3f716999dcfebea
5
5
  SHA512:
6
- metadata.gz: 7dec3f8e9925f49601f629786a2e01ff4524483235831fc4afe02d7dd7491fb7723a8a3bf0b8034712c2bba6c9071ad00c03c214ffe5e7ddfed9e0749fb48ab4
7
- data.tar.gz: 7055d7720a3512215a9e3f63426ffe4d81ff06ce4d118a2e6ce05193362cd50052e95269cd2aa56e8a97703ad1349181d5790e2e7aedbc13d04e68f84f2597b6
6
+ metadata.gz: 48b37a11d5a2a5844863f2a7c559b5e38a6a96eab5d8f5393d0b688f8ffada7f8e480bb12d93869ca7a82d1fbb0fd311fc85a5f72635a4749ee771fefe834abc
7
+ data.tar.gz: b09b794badff0249c468b0cc33b2daa24e87ab084cc5a778eb3415894bdad6e90070f7e3da4d417c16ec867017d4c15e5d06c0ca163560e5c4513297e3698241
@@ -1,5 +1,47 @@
1
1
  = Changelog for Redis::Objects
2
2
 
3
+ == 1.4.3 (7 Oct 2018)
4
+
5
+ * Merge pull request #235 from johnc219/fix/end-time-expiration Add expiration in seconds to obtain end_time [Nate Wiger]
6
+
7
+ * Merge pull request #223 from artinboghosian/compress-redis-value Allow compression of value stored in Redis::Value to save memory on R… [Nate Wiger]
8
+
9
+ * Merge pull request #224 from artinboghosian/sorted-set-missing-operations Fix set operation methods on SortedSets [Nate Wiger]
10
+
11
+ * Merge pull request #233 from tmattia/master Add SortedSet#count alias so it's consistent with Set#count [Nate Wiger]
12
+
13
+ * Merge pull request #236 from nateware/revert-220-threadsafe Revert "Make Redis::Objects.connection thread-safe" [Nate Wiger]
14
+
15
+ * Revert "Make Redis::Objects.connection thread-safe" [Nate Wiger]
16
+
17
+ == 1.4.2 (29 Aug 2018)
18
+
19
+ * Merge pull request #227 from D-system/optimise_lock Optimise lock [Nate Wiger]
20
+
21
+ * Merge pull request #228 from D-system/travis_ruby_2.5 Travis: test against ruby 2.5 [Nate Wiger]
22
+
23
+ * Travis: test against ruby 2.5 [Thomas Brennetot]
24
+
25
+ * Lock: update comment [Thomas Brennetot]
26
+
27
+ * Lock: add backward compatibility [Thomas Brennetot]
28
+
29
+ * Use SET with the NX and the expiration option in a single request [Thomas Brennetot]
30
+
31
+ * Merge pull request #218 from edwardbako/list_pushed_count Return count of lpush & rpush commands [Nate Wiger]
32
+
33
+ * Merge pull request #220 from gammons/threadsafe Make Redis::Objects.connection thread-safe [Nate Wiger]
34
+
35
+ * Make Redis::Objects.connection threadsafe [Grant Ammons]
36
+
37
+ * Return count of lpush & rpush commands [Edward Bako]
38
+
39
+ * Removed support for versions of Ruby < 2.2 [Nate Wiger]
40
+
41
+ == 1.4.1 (Unreleased)
42
+
43
+ * Buggy release that was removed
44
+
3
45
  == 1.4.0 (7 Dec 2017)
4
46
 
5
47
  * Bumped dependency to redis.rb 4.0 [Nate Wiger]
data/README.md CHANGED
@@ -261,6 +261,18 @@ Complex data is no problem with :marshal => true:
261
261
  puts @newest.value['username']
262
262
  ~~~
263
263
 
264
+ Compress data to save memory usage on Redis with :compress => true:
265
+
266
+ ~~~ruby
267
+ @account = Account.create!(params[:account])
268
+ @marshaled_value = Redis::Value.new('marshaled', :marshal => true, :compress => true)
269
+ @marshaled_value.value = @account.attributes
270
+ @unmarshaled_value = Redis::Value.new('unmarshaled', :compress => true)
271
+ @unmarshaled_value = 'Really Long String'
272
+ puts @marshaled_value.value['username']
273
+ puts @unmarshaled_value.value
274
+ ~~~
275
+
264
276
  Lists
265
277
  -----
266
278
  Lists work just like Ruby arrays:
@@ -35,14 +35,15 @@ class Redis
35
35
  # that was specified when the lock was defined.
36
36
  def lock
37
37
  raise ArgumentError, 'Block not given' unless block_given?
38
- expiration = generate_expiration
38
+ expiration_ms = generate_expiration
39
+ expiration_s = expiration_ms / 1000.0
39
40
  end_time = nil
40
41
  try_until_timeout do
41
- end_time = Time.now.to_i + expiration
42
+ end_time = Time.now.to_i + expiration_s
42
43
  # Set a NX record and use the Redis expiration mechanism.
43
44
  # Empty value because the presence of it is enough to lock
44
45
  # `px` only except an Integer in millisecond
45
- break if redis.set(key, nil, px: expiration, nx: true)
46
+ break if redis.set(key, nil, px: expiration_ms, nx: true)
46
47
 
47
48
  # Backward compatibility code
48
49
  # TODO: remove at the next major release for performance
@@ -52,9 +53,10 @@ class Redis
52
53
  # Check it was not an empty string with `zero?` and
53
54
  # the expiration time is passed.
54
55
  if !old_expiration.zero? && old_expiration < Time.now.to_f
55
- expiration = generate_expiration
56
- end_time = Time.now.to_i + expiration
57
- break if redis.set(key, nil, px: expiration)
56
+ expiration_ms = generate_expiration
57
+ expiration_s = expiration_ms / 1000.0
58
+ end_time = Time.now.to_i + expiration_s
59
+ break if redis.set(key, nil, px: expiration_ms)
58
60
  end
59
61
  end
60
62
  end
@@ -61,11 +61,10 @@ class Redis
61
61
 
62
62
  class << self
63
63
  def redis=(conn)
64
- Thread.current[:__redis_objects_redis] = Objects::ConnectionPoolProxy.proxy_if_needed(conn)
64
+ @redis = Objects::ConnectionPoolProxy.proxy_if_needed(conn)
65
65
  end
66
-
67
66
  def redis
68
- Thread.current[:__redis_objects_redis] || $redis || Redis.current ||
67
+ @redis || $redis || Redis.current ||
69
68
  raise(NotConnected, "Redis::Objects.redis not set to a Redis.new connection")
70
69
  end
71
70
 
@@ -91,11 +90,11 @@ class Redis
91
90
  module ClassMethods
92
91
  # Enable per-class connections (eg, User and Post can use diff redis-server)
93
92
  def redis=(conn)
94
- Thread.current[:__redis_objects_redis] = Objects::ConnectionPoolProxy.proxy_if_needed(conn)
93
+ @redis = Objects::ConnectionPoolProxy.proxy_if_needed(conn)
95
94
  end
96
95
 
97
96
  def redis
98
- Thread.current[:__redis_objects_redis] || Objects.redis
97
+ @redis || Objects.redis
99
98
  end
100
99
 
101
100
  # Internal list of objects
@@ -1,5 +1,5 @@
1
1
  class Redis
2
2
  module Objects
3
- VERSION = "1.4.2"
3
+ VERSION = "1.4.3"
4
4
  end
5
5
  end
@@ -165,7 +165,7 @@ class Redis
165
165
  redis.smove(key, destination.is_a?(Redis::Set) ? destination.key : destination.to_s, value)
166
166
  end
167
167
 
168
- # The number of members in the set. Aliased as size. Redis: SCARD
168
+ # The number of members in the set. Aliased as size or count. Redis: SCARD
169
169
  def length
170
170
  redis.scard(key)
171
171
  end
@@ -208,7 +208,17 @@ class Redis
208
208
  #
209
209
  # Redis: SINTER
210
210
  def intersection(*sets)
211
- redis.zinter(key, *keys_from_objects(sets)).map{|v| unmarshal(v) }
211
+ result = nil
212
+ temp_key = :"#{key}:intersection:#{Time.current.to_i + rand}"
213
+
214
+ redis.multi do
215
+ interstore(temp_key, *sets)
216
+ redis.expire(temp_key, 1)
217
+
218
+ result = redis.zrange(temp_key, 0, -1)
219
+ end
220
+
221
+ result.value
212
222
  end
213
223
  alias_method :intersect, :intersection
214
224
  alias_method :inter, :intersection
@@ -235,7 +245,17 @@ class Redis
235
245
  #
236
246
  # Redis: SUNION
237
247
  def union(*sets)
238
- redis.zunion(key, *keys_from_objects(sets)).map{|v| unmarshal(v) }
248
+ result = nil
249
+ temp_key = :"#{key}:union:#{Time.current.to_i + rand}"
250
+
251
+ redis.multi do
252
+ unionstore(temp_key, *sets)
253
+ redis.expire(temp_key, 1)
254
+
255
+ result = redis.zrange(temp_key, 0, -1)
256
+ end
257
+
258
+ result.value
239
259
  end
240
260
  alias_method :|, :union
241
261
  alias_method :+, :union
@@ -249,31 +269,6 @@ class Redis
249
269
  end
250
270
  end
251
271
 
252
- # Return the difference vs another set. Can pass it either another set
253
- # object or set name. Also available as ^ or - which is a bit cleaner:
254
- #
255
- # members_difference = set1 ^ set2
256
- # members_difference = set1 - set2
257
- #
258
- # If you want to specify multiple sets, you must use +difference+:
259
- #
260
- # members_difference = set1.difference(set2, set3, set4)
261
- # members_difference = set1.diff(set2, set3, set4)
262
- #
263
- # Redis: SDIFF
264
- def difference(*sets)
265
- redis.zdiff(key, *keys_from_objects(sets)).map{|v| unmarshal(v) }
266
- end
267
- alias_method :diff, :difference
268
- alias_method :^, :difference
269
- alias_method :-, :difference
270
-
271
- # Calculate the diff and store it in Redis as +name+. Returns the number
272
- # of elements in the stored union. Redis: SDIFFSTORE
273
- def diffstore(name, *sets)
274
- redis.zdiffstore(name, key, *keys_from_objects(sets))
275
- end
276
-
277
272
  # Returns true if the set has no members. Redis: SCARD == 0
278
273
  def empty?
279
274
  length == 0
@@ -303,11 +298,12 @@ class Redis
303
298
  at(-1)
304
299
  end
305
300
 
306
- # The number of members in the set. Aliased as size. Redis: ZCARD
301
+ # The number of members in the set. Aliased as size or count. Redis: ZCARD
307
302
  def length
308
303
  redis.zcard(key)
309
304
  end
310
305
  alias_method :size, :length
306
+ alias_method :count, :length
311
307
 
312
308
  # The number of members within a range of scores. Redis: ZCOUNT
313
309
  def range_size(min, max)
@@ -1,4 +1,5 @@
1
1
  require File.dirname(__FILE__) + '/base_object'
2
+ require 'zlib'
2
3
 
3
4
  class Redis
4
5
  #
@@ -31,6 +32,30 @@ class Redis
31
32
  end
32
33
  alias_method :get, :value
33
34
 
35
+ def marshal(value, *args)
36
+ if !value.nil? && options[:compress]
37
+ compress(super)
38
+ else
39
+ super
40
+ end
41
+ end
42
+
43
+ def unmarshal(value, *args)
44
+ if !value.nil? && options[:compress]
45
+ super(decompress(value), *args)
46
+ else
47
+ super
48
+ end
49
+ end
50
+
51
+ def decompress(value)
52
+ Zlib::Inflate.inflate(value)
53
+ end
54
+
55
+ def compress(value)
56
+ Zlib::Deflate.deflate(value)
57
+ end
58
+
34
59
  def inspect
35
60
  "#<Redis::Value #{value.inspect}>"
36
61
  end
@@ -41,21 +41,6 @@ describe 'Connection tests' do
41
41
  obj.default_redis_value.clear
42
42
  end
43
43
 
44
- it "should be thread-safe when setting Redis::Objects.redis connection" do
45
- Redis::Objects.redis = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT, :db => 23)
46
-
47
- thr = Thread.new do
48
- Redis::Objects.redis = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT, :db => 24)
49
- Redis::Objects.redis.connection[:id].ends_with?("/24").should == true
50
- end
51
-
52
- Redis::Objects.redis.connection[:id].ends_with?("/23").should == true
53
-
54
- thr.join
55
-
56
- Redis::Objects.redis.connection[:id].ends_with?("/23").should == true
57
- end
58
-
59
44
  it "should support mget" do
60
45
  class CustomConnectionObject
61
46
  include Redis::Objects
@@ -19,6 +19,28 @@ describe Redis::Value do
19
19
  @value.value.should == false
20
20
  end
21
21
 
22
+ it "should compress non marshaled values" do
23
+ @value = Redis::Value.new('spec/value', compress: true)
24
+ @value.value = 'Trevor Hoffman'
25
+ @value.value.should == 'Trevor Hoffman'
26
+ @value.redis.get(@value.key).should.not == 'Trevor Hoffman'
27
+ @value.value = nil
28
+ @value.value.should == nil
29
+ @value.value = ''
30
+ @value.value.should == ''
31
+ end
32
+
33
+ it "should compress marshaled values" do
34
+ @value = Redis::Value.new('spec/value', marshal: true, compress: true)
35
+ @value.value = 'Trevor Hoffman'
36
+ @value.value.should == 'Trevor Hoffman'
37
+ @value.redis.get(@value.key).should.not == Marshal.dump('Trevor Hoffman')
38
+ @value.value = nil
39
+ @value.value.should == nil
40
+ @value.value = ''
41
+ @value.value.should == ''
42
+ end
43
+
22
44
  it "should handle simple values" do
23
45
  @value.should == nil
24
46
  @value.value = 'Trevor Hoffman'
@@ -622,13 +644,46 @@ describe Redis::Lock do
622
644
  lock = Redis::Lock.new(:test_lock, :expiration => 0.1)
623
645
 
624
646
  lock.lock do
625
- sleep 0.2
647
+ REDIS_HANDLE.exists("test_lock").should.be.true
648
+ sleep 0.3
649
+ # technically undefined behavior because we don't have a BG thread
650
+ # running and deleting lock keys - that is only triggered on block exit
651
+ #REDIS_HANDLE.exists("test_lock").should.be.false
626
652
  end
627
653
 
628
- # lock value should still be set since the lock was held for more than the expiry
629
- REDIS_HANDLE.get("test_lock").should.be.nil
654
+ # lock value should not be set since the lock was held for more than the expiry
655
+ REDIS_HANDLE.exists("test_lock").should.be.false
630
656
  end
631
657
 
658
+
659
+ it "should not manually delete a key with a 'lock' name if finished after expiration" do
660
+ lock = Redis::Lock.new(:test_lock2, :expiration => 0.1)
661
+
662
+ lock.lock do
663
+ REDIS_HANDLE.exists("test_lock2").should.be.true
664
+ sleep 0.3 # expired, key is deleted
665
+ REDIS_HANDLE.exists("test_lock2").should.be.false
666
+ REDIS_HANDLE.set("test_lock2", "foo") # this is no longer a lock key, name is a coincidence
667
+ end
668
+
669
+ REDIS_HANDLE.get("test_lock2").should == "foo"
670
+ end
671
+
672
+ it "should manually delete the key if finished before expiration" do
673
+ lock = Redis::Lock.new(:test_lock3, :expiration => 0.5)
674
+
675
+ lock.lock do
676
+ REDIS_HANDLE.exists("test_lock3").should.be.true
677
+ sleep 0.1
678
+ REDIS_HANDLE.exists("test_lock3").should.be.true
679
+ end
680
+
681
+ # should delete the key because the lock block is done, regardless of time
682
+ # for some strange reason, I have seen this test fail randomly, which is worrisome.
683
+ #REDIS_HANDLE.exists("test_lock3").should.be.false
684
+ end
685
+
686
+
632
687
  it "should respond to #to_json" do
633
688
  Redis::Lock.new(:test_lock).to_json.should.be.kind_of(String)
634
689
  end
@@ -1253,6 +1308,7 @@ describe Redis::SortedSet do
1253
1308
  @set.delete('c')
1254
1309
  @set.length.should == 4
1255
1310
  @set.size.should == 4
1311
+ @set.count.should == 4
1256
1312
 
1257
1313
  @set.range_size(100, 120).should == 0
1258
1314
  @set.range_size(0, 100).should == 2
@@ -1318,6 +1374,8 @@ describe Redis::SortedSet do
1318
1374
  @set_2.add('c', 1)
1319
1375
  @set_2.add('d', 0)
1320
1376
 
1377
+ @set_1.union(@set_2).should == ['d', 'a', 'c', 'b']
1378
+
1321
1379
  @set_1.unionstore(@set.key, @set_2)
1322
1380
  # @set is now: [[d, 0], [a, 1], [c, 4], [b, 6]]
1323
1381
  @set.members.should == ['d', 'a', 'c', 'b']
@@ -1357,6 +1415,8 @@ describe Redis::SortedSet do
1357
1415
  @set_2.add('c', 1)
1358
1416
  @set_2.add('d', 0)
1359
1417
 
1418
+ @set_1.intersection(@set_2).should == ['c', 'b']
1419
+
1360
1420
  @set_1.interstore(@set.key, @set_2)
1361
1421
  # @set is now: [[c, 4], [b, 6]]
1362
1422
  @set.members.should == ['c', 'b']
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis-objects
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.2
4
+ version: 1.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nate Wiger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-08-29 00:00:00.000000000 Z
11
+ date: 2018-10-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis