redis-objects 1.4.2 → 1.4.3

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: 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