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 +4 -4
- data/CHANGELOG.rdoc +42 -0
- data/README.md +12 -0
- data/lib/redis/lock.rb +8 -6
- data/lib/redis/objects.rb +4 -5
- data/lib/redis/objects/version.rb +1 -1
- data/lib/redis/set.rb +1 -1
- data/lib/redis/sorted_set.rb +24 -28
- data/lib/redis/value.rb +25 -0
- data/spec/redis_objects_conn_spec.rb +0 -15
- data/spec/redis_objects_instance_spec.rb +63 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6a9f86f294c2283b6ceae1730dfe6f1d1c3665ac9733cd107a4aa522d8a66bda
|
4
|
+
data.tar.gz: 50d631298aff5bcd5b15179c1a700a56a512c4a096cedad4c3f716999dcfebea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 48b37a11d5a2a5844863f2a7c559b5e38a6a96eab5d8f5393d0b688f8ffada7f8e480bb12d93869ca7a82d1fbb0fd311fc85a5f72635a4749ee771fefe834abc
|
7
|
+
data.tar.gz: b09b794badff0249c468b0cc33b2daa24e87ab084cc5a778eb3415894bdad6e90070f7e3da4d417c16ec867017d4c15e5d06c0ca163560e5c4513297e3698241
|
data/CHANGELOG.rdoc
CHANGED
@@ -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:
|
data/lib/redis/lock.rb
CHANGED
@@ -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
|
-
|
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 +
|
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:
|
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
|
-
|
56
|
-
|
57
|
-
|
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
|
data/lib/redis/objects.rb
CHANGED
@@ -61,11 +61,10 @@ class Redis
|
|
61
61
|
|
62
62
|
class << self
|
63
63
|
def redis=(conn)
|
64
|
-
|
64
|
+
@redis = Objects::ConnectionPoolProxy.proxy_if_needed(conn)
|
65
65
|
end
|
66
|
-
|
67
66
|
def redis
|
68
|
-
|
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
|
-
|
93
|
+
@redis = Objects::ConnectionPoolProxy.proxy_if_needed(conn)
|
95
94
|
end
|
96
95
|
|
97
96
|
def redis
|
98
|
-
|
97
|
+
@redis || Objects.redis
|
99
98
|
end
|
100
99
|
|
101
100
|
# Internal list of objects
|
data/lib/redis/set.rb
CHANGED
@@ -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
|
data/lib/redis/sorted_set.rb
CHANGED
@@ -208,7 +208,17 @@ class Redis
|
|
208
208
|
#
|
209
209
|
# Redis: SINTER
|
210
210
|
def intersection(*sets)
|
211
|
-
|
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
|
-
|
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)
|
data/lib/redis/value.rb
CHANGED
@@ -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
|
-
|
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
|
629
|
-
REDIS_HANDLE.
|
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.
|
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-
|
11
|
+
date: 2018-10-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|