redis-objects 1.4.3 → 1.6.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 +4 -4
- data/.gitignore +2 -0
- data/.travis.yml +9 -4
- data/CHANGELOG.rdoc +37 -0
- data/README.md +40 -9
- data/lib/redis/base_object.rb +6 -0
- data/lib/redis/counter.rb +2 -6
- data/lib/redis/enumerable_object.rb +28 -0
- data/lib/redis/hash_key.rb +10 -38
- data/lib/redis/helpers/core_commands.rb +16 -11
- data/lib/redis/list.rb +2 -19
- data/lib/redis/lock.rb +0 -8
- data/lib/redis/objects/connection_pool_proxy.rb +1 -0
- data/lib/redis/objects/hashes.rb +9 -0
- data/lib/redis/objects/lists.rb +9 -0
- data/lib/redis/objects/sets.rb +9 -0
- data/lib/redis/objects/version.rb +1 -1
- data/lib/redis/objects.rb +9 -4
- data/lib/redis/set.rb +4 -21
- data/lib/redis/sorted_set.rb +6 -13
- data/lib/redis/value.rb +0 -5
- data/redis-objects.gemspec +5 -1
- data/spec/redis_autoload_objects_spec.rb +1 -1
- data/spec/redis_objects_conn_spec.rb +16 -25
- data/spec/redis_objects_custom_serializer.rb +199 -0
- data/spec/redis_objects_instance_spec.rb +151 -38
- data/spec/redis_objects_model_spec.rb +85 -3
- data/spec/spec_helper.rb +15 -2
- metadata +38 -8
data/lib/redis/value.rb
CHANGED
@@ -6,11 +6,6 @@ class Redis
|
|
6
6
|
# Class representing a simple value. You can use standard Ruby operations on it.
|
7
7
|
#
|
8
8
|
class Value < BaseObject
|
9
|
-
require 'redis/helpers/core_commands'
|
10
|
-
include Redis::Helpers::CoreCommands
|
11
|
-
|
12
|
-
attr_reader :key, :options
|
13
|
-
|
14
9
|
def value=(val)
|
15
10
|
allow_expiration do
|
16
11
|
if val.nil?
|
data/redis-objects.gemspec
CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
# Only fix this one version or else tests break
|
22
|
-
spec.add_dependency "redis", "
|
22
|
+
spec.add_dependency "redis", "< 4.6"
|
23
23
|
|
24
24
|
# Ignore gemspec warnings on these. Trying to fix them to versions breaks TravisCI
|
25
25
|
spec.add_development_dependency "bundler"
|
@@ -29,6 +29,10 @@ Gem::Specification.new do |spec|
|
|
29
29
|
|
30
30
|
# Compatibility testing
|
31
31
|
spec.add_development_dependency "redis-namespace"
|
32
|
+
spec.add_development_dependency "activesupport"
|
32
33
|
spec.add_development_dependency "activerecord"
|
33
34
|
spec.add_development_dependency "sqlite3"
|
35
|
+
|
36
|
+
# Code coverage
|
37
|
+
spec.add_development_dependency "simplecov-cobertura"
|
34
38
|
end
|
@@ -4,7 +4,7 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
4
4
|
# tests whether autoload functionality works correctly; had issues previously
|
5
5
|
|
6
6
|
require 'redis/objects'
|
7
|
-
|
7
|
+
Redis::Objects.redis = REDIS_HANDLE
|
8
8
|
|
9
9
|
describe 'Redis::Objects' do
|
10
10
|
it "should autoload everything" do
|
@@ -5,6 +5,7 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
5
5
|
|
6
6
|
require 'redis/objects'
|
7
7
|
require 'connection_pool'
|
8
|
+
Redis::Objects.redis = REDIS_HANDLE
|
8
9
|
|
9
10
|
BAD_REDIS = "totally bad bogus redis handle"
|
10
11
|
|
@@ -95,13 +96,13 @@ describe 'Connection tests' do
|
|
95
96
|
end
|
96
97
|
|
97
98
|
it "should support local handles with a vanilla redis connection" do
|
98
|
-
Redis.current = nil # reset from other tests
|
99
|
+
# Redis.current = nil # reset from other tests
|
99
100
|
Redis::Objects.redis = nil
|
100
101
|
@redis_handle = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT)
|
101
102
|
|
102
103
|
# Redis.current is lazily auto-populated to touch 6379
|
103
104
|
# This why we choose the weird 9212 port to avoid
|
104
|
-
Redis.current.inspect.should == Redis.new.inspect
|
105
|
+
# Redis.current.inspect.should == Redis.new.inspect
|
105
106
|
Redis::Objects.redis.inspect.should == Redis.new.inspect
|
106
107
|
|
107
108
|
v = Redis::Value.new('conn/value', @redis_handle)
|
@@ -140,13 +141,13 @@ describe 'Connection tests' do
|
|
140
141
|
end
|
141
142
|
|
142
143
|
it "should support local handles with a connection_pool" do
|
143
|
-
Redis.current = nil # reset from other tests
|
144
|
+
# Redis.current = nil # reset from other tests
|
144
145
|
Redis::Objects.redis = nil
|
145
146
|
@redis_handle = ConnectionPool.new { Redis.new(:host => REDIS_HOST, :port => REDIS_PORT) }
|
146
147
|
|
147
148
|
# Redis.current is lazily auto-populated to touch 6379
|
148
149
|
# This why we choose the weird 9212 port to avoid
|
149
|
-
Redis.current.inspect.should == Redis.new.inspect
|
150
|
+
# Redis.current.inspect.should == Redis.new.inspect
|
150
151
|
Redis::Objects.redis.inspect.should == Redis.new.inspect
|
151
152
|
|
152
153
|
v = Redis::Value.new('conn/value', @redis_handle)
|
@@ -184,24 +185,19 @@ describe 'Connection tests' do
|
|
184
185
|
c.decr(1)
|
185
186
|
end
|
186
187
|
|
187
|
-
it "should support
|
188
|
-
Redis.current
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
Redis::
|
193
|
-
|
194
|
-
Redis::SortedSet.new('conn/zset').should == ['d', 'b', 'a', 'c']
|
195
|
-
Redis::Counter.new('conn/counter').should == 2
|
188
|
+
it "should properly support fallback handle variables" do
|
189
|
+
# Redis.current is lazily auto-populated to touch 6379
|
190
|
+
# This why we choose the weird 9212 port to avoid
|
191
|
+
old_redis = $redis
|
192
|
+
$redis = BAD_REDIS
|
193
|
+
Redis::Objects.redis.should == BAD_REDIS
|
194
|
+
$redis = old_redis
|
196
195
|
end
|
197
196
|
|
198
197
|
it "should support Redis::Objects.redis= with a connection_pool" do
|
198
|
+
# reset redis
|
199
199
|
@redis_handle = ConnectionPool.new { Redis.new(:host => REDIS_HOST, :port => REDIS_PORT) }
|
200
|
-
|
201
|
-
# Redis.current is lazily auto-populated to touch 6379
|
202
|
-
# This why we choose the weird 9212 port to avoid
|
203
|
-
Redis.current = BAD_REDIS
|
204
|
-
Redis::Objects.redis.should == BAD_REDIS
|
200
|
+
Redis::Objects.redis = @redis_handle
|
205
201
|
|
206
202
|
# This set of tests sucks, it fucks up the per-data-type handles
|
207
203
|
# because Redis.current is then set to a BS value, and the lazy
|
@@ -229,13 +225,8 @@ describe 'Connection tests' do
|
|
229
225
|
|
230
226
|
it "should support Redis::Objects.redis= with a vanilla redis connection" do
|
231
227
|
# reset redis
|
232
|
-
Redis::Objects.redis = nil
|
233
228
|
@redis_handle = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT)
|
234
|
-
|
235
|
-
# Redis.current is lazily auto-populated to touch 6379
|
236
|
-
# This why we choose the weird 9212 port to avoid
|
237
|
-
Redis.current = BAD_REDIS
|
238
|
-
Redis::Objects.redis.should == BAD_REDIS
|
229
|
+
Redis::Objects.redis = @redis_handle
|
239
230
|
|
240
231
|
# This set of tests sucks, it fucks up the per-data-type handles
|
241
232
|
# because Redis.current is then set to a BS value, and the lazy
|
@@ -260,7 +251,7 @@ describe 'Connection tests' do
|
|
260
251
|
Redis::Counter.new('conn/counter').should == 2
|
261
252
|
|
262
253
|
# Fix for future tests
|
263
|
-
Redis.current = @redis_handle
|
254
|
+
# Redis.current = @redis_handle
|
264
255
|
end
|
265
256
|
|
266
257
|
it "should support pipelined changes" do
|
@@ -0,0 +1,199 @@
|
|
1
|
+
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
3
|
+
|
4
|
+
require 'redis/objects'
|
5
|
+
Redis::Objects.redis = REDIS_HANDLE
|
6
|
+
|
7
|
+
class CustomSerializer
|
8
|
+
class << self
|
9
|
+
attr_accessor :dump_called, :load_called, :dump_args, :load_args
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.dump(value, *args, **kargs)
|
13
|
+
@dump_called = true
|
14
|
+
@dump_args = [args, kargs]
|
15
|
+
Marshal.dump(value)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.load(value, *args, **kargs)
|
19
|
+
@load_called = true
|
20
|
+
@load_args = [args, kargs]
|
21
|
+
Marshal.load(value)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.reset!
|
25
|
+
@dump_called = nil
|
26
|
+
@load_called = nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'with custom serialization' do
|
31
|
+
before do
|
32
|
+
CustomSerializer.reset!
|
33
|
+
end
|
34
|
+
|
35
|
+
describe Redis::Value do
|
36
|
+
before do
|
37
|
+
@value = Redis::Value.new(
|
38
|
+
'spec/value_custom_serializer',
|
39
|
+
marshal: true,
|
40
|
+
serializer: CustomSerializer
|
41
|
+
)
|
42
|
+
@value.clear
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'uses custom serializer' do
|
46
|
+
@value.value = { json: 'data' }
|
47
|
+
CustomSerializer.dump_called.should == true
|
48
|
+
CustomSerializer.load_called.should == nil
|
49
|
+
@value.value.should == { json: 'data' }
|
50
|
+
CustomSerializer.dump_called.should == true
|
51
|
+
CustomSerializer.load_called.should == true
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'passes extra arguments to dump' do
|
55
|
+
@value.options[:marshal_dump_args] = ['some', { extra: 'arguments' }]
|
56
|
+
@value.value = 1
|
57
|
+
CustomSerializer.dump_args.should == [['some'], { extra: 'arguments' }]
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'passes extra arguments to load' do
|
61
|
+
@value.options[:marshal_load_args] = ['some', { extra: 'arguments' }]
|
62
|
+
@value.value = 1
|
63
|
+
@value.value.should == 1
|
64
|
+
CustomSerializer.load_args.should == [['some'], { extra: 'arguments' }]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe Redis::List do
|
69
|
+
before do
|
70
|
+
@list = Redis::List.new(
|
71
|
+
'spec/list_custom_serializer',
|
72
|
+
marshal: true,
|
73
|
+
serializer: CustomSerializer
|
74
|
+
)
|
75
|
+
@list.clear
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'uses custom serializer' do
|
79
|
+
@list << { json: 'data' }
|
80
|
+
CustomSerializer.dump_called.should == true
|
81
|
+
CustomSerializer.load_called.should == nil
|
82
|
+
@list.should == [{ json: 'data' }]
|
83
|
+
CustomSerializer.dump_called.should == true
|
84
|
+
CustomSerializer.load_called.should == true
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'passes extra arguments to dump' do
|
88
|
+
@list.options[:marshal_dump_args] = ['some', { extra: 'arguments' }]
|
89
|
+
@list << 1
|
90
|
+
CustomSerializer.dump_args.should == [['some'], { extra: 'arguments' }]
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'passes extra arguments to load' do
|
94
|
+
@list.options[:marshal_load_args] = ['some', { extra: 'arguments' }]
|
95
|
+
@list << 1
|
96
|
+
@list.values.should == [1]
|
97
|
+
CustomSerializer.load_args.should == [['some'], { extra: 'arguments' }]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe Redis::HashKey do
|
102
|
+
before do
|
103
|
+
@hash = Redis::HashKey.new(
|
104
|
+
'spec/hash_custom_serializer',
|
105
|
+
marshal: true,
|
106
|
+
serializer: CustomSerializer
|
107
|
+
)
|
108
|
+
@hash.clear
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'uses custom serializer' do
|
112
|
+
@hash['a'] = 1
|
113
|
+
CustomSerializer.dump_called.should == true
|
114
|
+
CustomSerializer.load_called.should == nil
|
115
|
+
@hash.value.should == { 'a' => 1 }
|
116
|
+
CustomSerializer.dump_called.should == true
|
117
|
+
CustomSerializer.load_called.should == true
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'passes extra arguments to dump' do
|
121
|
+
@hash.options[:marshal_dump_args] = ['some', { extra: 'arguments' }]
|
122
|
+
@hash['a'] = 1
|
123
|
+
CustomSerializer.dump_args.should == [['some'], { extra: 'arguments' }]
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'passes extra arguments to load' do
|
127
|
+
@hash.options[:marshal_load_args] = ['some', { extra: 'arguments' }]
|
128
|
+
@hash['a'] = 1
|
129
|
+
@hash.value.should == { 'a' => 1 }
|
130
|
+
CustomSerializer.load_args.should == [['some'], { extra: 'arguments' }]
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
describe Redis::Set do
|
135
|
+
before do
|
136
|
+
@set = Redis::Set.new(
|
137
|
+
'spec/set_custom_serializer',
|
138
|
+
marshal: true,
|
139
|
+
serializer: CustomSerializer
|
140
|
+
)
|
141
|
+
@set.clear
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'uses custom serializer' do
|
145
|
+
@set << 'a'
|
146
|
+
CustomSerializer.dump_called.should == true
|
147
|
+
CustomSerializer.load_called.should == nil
|
148
|
+
@set.members.should == ['a']
|
149
|
+
CustomSerializer.dump_called.should == true
|
150
|
+
CustomSerializer.load_called.should == true
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'passes extra arguments to dump' do
|
154
|
+
@set.options[:marshal_dump_args] = ['some', { extra: 'arguments' }]
|
155
|
+
@set << 'a'
|
156
|
+
CustomSerializer.dump_args.should == [['some'], { extra: 'arguments' }]
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'passes extra arguments to load' do
|
160
|
+
@set.options[:marshal_load_args] = ['some', { extra: 'arguments' }]
|
161
|
+
@set << 'a'
|
162
|
+
@set.members.should == ['a']
|
163
|
+
CustomSerializer.load_args.should == [['some'], { extra: 'arguments' }]
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
describe Redis::SortedSet do
|
168
|
+
before do
|
169
|
+
@set = Redis::SortedSet.new(
|
170
|
+
'spec/zset_custom_serializer',
|
171
|
+
marshal: true,
|
172
|
+
serializer: CustomSerializer
|
173
|
+
)
|
174
|
+
@set.clear
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'uses custom serializer' do
|
178
|
+
@set['a'] = 1
|
179
|
+
CustomSerializer.dump_called.should == true
|
180
|
+
CustomSerializer.load_called.should == nil
|
181
|
+
@set.members.should == ['a']
|
182
|
+
CustomSerializer.dump_called.should == true
|
183
|
+
CustomSerializer.load_called.should == true
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'passes extra arguments to dump' do
|
187
|
+
@set.options[:marshal_dump_args] = ['some', { extra: 'arguments' }]
|
188
|
+
@set['a'] = 1
|
189
|
+
CustomSerializer.dump_args.should == [['some'], { extra: 'arguments' }]
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'passes extra arguments to load' do
|
193
|
+
@set.options[:marshal_load_args] = ['some', { extra: 'arguments' }]
|
194
|
+
@set['a'] = 1
|
195
|
+
@set.members.should == ['a']
|
196
|
+
CustomSerializer.load_args.should == [['some'], { extra: 'arguments' }]
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
3
3
|
|
4
4
|
require 'redis/objects'
|
5
|
+
Redis::Objects.redis = REDIS_HANDLE
|
5
6
|
|
6
7
|
describe Redis::Value do
|
7
8
|
before do
|
@@ -19,6 +20,21 @@ describe Redis::Value do
|
|
19
20
|
@value.value.should == false
|
20
21
|
end
|
21
22
|
|
23
|
+
it "should handle simple values" do
|
24
|
+
@value.should == nil
|
25
|
+
@value.value = 'Trevor Hoffman'
|
26
|
+
@value.should == 'Trevor Hoffman'
|
27
|
+
@value.get.should == 'Trevor Hoffman'
|
28
|
+
@value.exists?.should == true
|
29
|
+
@value.exists.should == 1
|
30
|
+
@value.del.should == 1
|
31
|
+
@value.should.be.nil
|
32
|
+
@value.exists?.should == false
|
33
|
+
@value.exists.should == 0
|
34
|
+
@value.value = 42
|
35
|
+
@value.value.should == '42'
|
36
|
+
end
|
37
|
+
|
22
38
|
it "should compress non marshaled values" do
|
23
39
|
@value = Redis::Value.new('spec/value', compress: true)
|
24
40
|
@value.value = 'Trevor Hoffman'
|
@@ -39,17 +55,8 @@ describe Redis::Value do
|
|
39
55
|
@value.value.should == nil
|
40
56
|
@value.value = ''
|
41
57
|
@value.value.should == ''
|
42
|
-
|
43
|
-
|
44
|
-
it "should handle simple values" do
|
45
|
-
@value.should == nil
|
46
|
-
@value.value = 'Trevor Hoffman'
|
47
|
-
@value.should == 'Trevor Hoffman'
|
48
|
-
@value.get.should == 'Trevor Hoffman'
|
49
|
-
@value.del.should == 1
|
50
|
-
@value.should.be.nil
|
51
|
-
@value.value = 42
|
52
|
-
@value.value.should == '42'
|
58
|
+
@value.delete
|
59
|
+
@value.value.should.be.nil
|
53
60
|
end
|
54
61
|
|
55
62
|
it "should handle complex marshaled values" do
|
@@ -88,7 +95,7 @@ describe Redis::Value do
|
|
88
95
|
marshalled_string = Marshal.dump({json: 'marshal'})
|
89
96
|
@value = Redis::Value.new('spec/marshal', :default => marshalled_string, :marshal => true)
|
90
97
|
@value.value.should == marshalled_string
|
91
|
-
@value.
|
98
|
+
@value.delete
|
92
99
|
end
|
93
100
|
|
94
101
|
it "should support renaming values" do
|
@@ -499,23 +506,56 @@ describe Redis::Counter do
|
|
499
506
|
@counter.incrbyfloat 2.0e2
|
500
507
|
@counter.to_f.should == 5214.31
|
501
508
|
@counter.clear
|
509
|
+
@counter.should.be.nil
|
502
510
|
end
|
503
511
|
|
504
512
|
it "should support an atomic block" do
|
505
513
|
@counter = Redis::Counter.new("spec/block_counter")
|
506
514
|
@counter.should == 0
|
507
515
|
@counter.increment(1)
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
516
|
+
|
517
|
+
# successfully increments
|
518
|
+
@updated = @counter.increment(1) { |updated| updated == 2 ? 'yep' : nil }
|
519
|
+
@updated.should == 'yep'
|
520
|
+
@counter.should == 2
|
521
|
+
|
522
|
+
# fails to increment
|
523
|
+
@updated = @counter.increment(1) { |updated| updated == 2 ? 'yep' : nil }
|
524
|
+
@updated.should == nil
|
525
|
+
@counter.should == 2
|
526
|
+
|
527
|
+
# successfully increments by float
|
528
|
+
@updated = @counter.incrbyfloat(1.5) { |updated| updated == 3.5 ? 'yep' : nil }
|
529
|
+
@updated.should == 'yep'
|
530
|
+
@counter.should == 3.5
|
531
|
+
|
532
|
+
# fails to increment by float
|
533
|
+
@updated = @counter.incrbyfloat(2.5) { |updated| updated == 5 ? 'yep' : nil }
|
534
|
+
@updated.should == nil
|
535
|
+
@counter.should == 3.5
|
536
|
+
|
537
|
+
# fails to decrement by float
|
538
|
+
@updated = @counter.decrbyfloat(0.5) { |updated| updated == 5 ? 'yep' : nil }
|
539
|
+
@updated.should == nil
|
540
|
+
@counter.should == 3.5
|
541
|
+
|
542
|
+
# successfully decrements by float
|
543
|
+
@updated = @counter.decrbyfloat(0.5) { |updated| updated == 3 ? 'yep' : nil }
|
544
|
+
@updated.should == 'yep'
|
545
|
+
@counter.should == 3
|
546
|
+
|
547
|
+
# fails to decrement
|
548
|
+
@updated = @counter.decrement(1) { |updated| updated == 3 ? 'yep' : nil }
|
549
|
+
@updated.should == nil
|
550
|
+
@counter.should == 3
|
551
|
+
|
552
|
+
# successfully decrements
|
553
|
+
@updated = @counter.decrement(1) { |updated| updated == 2 ? 'yep' : nil }
|
517
554
|
@updated.should == 'yep'
|
518
555
|
@counter.should == 2
|
556
|
+
|
557
|
+
@counter.value = nil
|
558
|
+
@counter.should == 0
|
519
559
|
end
|
520
560
|
|
521
561
|
it "should support #to_json" do
|
@@ -615,7 +655,7 @@ describe Redis::Lock do
|
|
615
655
|
REDIS_HANDLE.get("test_lock").should.be.nil
|
616
656
|
end
|
617
657
|
|
618
|
-
it "should not let
|
658
|
+
it "should not let blocks execute if they timeout" do
|
619
659
|
expiry = 15
|
620
660
|
lock = Redis::Lock.new(:test_lock, :expiration => expiry, :timeout => 0.1)
|
621
661
|
|
@@ -640,19 +680,68 @@ describe Redis::Lock do
|
|
640
680
|
REDIS_HANDLE.get("test_lock").should.not.be.nil
|
641
681
|
end
|
642
682
|
|
683
|
+
it "should handle a timeout of 0" do
|
684
|
+
expiry = 15
|
685
|
+
lock = Redis::Lock.new(:test_lock, :timeout => 0)
|
686
|
+
|
687
|
+
# create a fake lock
|
688
|
+
REDIS_HANDLE.set("test_lock", (Time.now + expiry).to_f)
|
689
|
+
|
690
|
+
gotit = false
|
691
|
+
error = nil
|
692
|
+
begin
|
693
|
+
lock.lock do
|
694
|
+
gotit = true
|
695
|
+
end
|
696
|
+
rescue => error
|
697
|
+
end
|
698
|
+
|
699
|
+
error.should.be.kind_of(Redis::Lock::LockTimeout)
|
700
|
+
|
701
|
+
# should not have the lock
|
702
|
+
gotit.should.not.be.true
|
703
|
+
|
704
|
+
# lock value should still be set
|
705
|
+
REDIS_HANDLE.get("test_lock").should.not.be.nil
|
706
|
+
end
|
707
|
+
|
708
|
+
it "should properly keep the lock across threads" do
|
709
|
+
lock = Redis::Lock.new(:test_lock0)
|
710
|
+
|
711
|
+
t1 = Thread.new do
|
712
|
+
lock.lock do
|
713
|
+
lock.exists?.should.be.true if RUNNING_LOCALLY
|
714
|
+
REDIS_HANDLE.exists?("test_lock0").should.be.true if RUNNING_LOCALLY
|
715
|
+
sleep 1.0 # hang onto the lock across other thread
|
716
|
+
end
|
717
|
+
end
|
718
|
+
|
719
|
+
t2 = Thread.new do
|
720
|
+
# check for the lock from another thread
|
721
|
+
lock.exists?.should.be.true if RUNNING_LOCALLY
|
722
|
+
REDIS_HANDLE.exists?("test_lock0").should.be.true if RUNNING_LOCALLY
|
723
|
+
end
|
724
|
+
|
725
|
+
t1.join
|
726
|
+
t2.join
|
727
|
+
|
728
|
+
# lock value should not be set since the lock was held for more than the expiry
|
729
|
+
lock.exists?.should.be.false
|
730
|
+
REDIS_HANDLE.exists?("test_lock0").should.be.false
|
731
|
+
end
|
732
|
+
|
643
733
|
it "Redis should remove the key if lock is held past expiration" do
|
644
|
-
lock = Redis::Lock.new(:
|
734
|
+
lock = Redis::Lock.new(:test_lock1, :expiration => 0.1)
|
645
735
|
|
646
736
|
lock.lock do
|
647
|
-
|
648
|
-
|
649
|
-
#
|
650
|
-
# running and deleting lock keys - that is only triggered on block exit
|
651
|
-
#REDIS_HANDLE.exists("test_lock").should.be.false
|
737
|
+
lock.exists?.should.be.true
|
738
|
+
REDIS_HANDLE.exists?("test_lock1").should.be.true
|
739
|
+
sleep 1.0 # hang onto the lock > expiry
|
652
740
|
end
|
653
741
|
|
654
742
|
# lock value should not be set since the lock was held for more than the expiry
|
655
|
-
|
743
|
+
lock.exists?.should.be.false
|
744
|
+
REDIS_HANDLE.exists?("test_lock1").should.be.false
|
656
745
|
end
|
657
746
|
|
658
747
|
|
@@ -660,9 +749,9 @@ describe Redis::Lock do
|
|
660
749
|
lock = Redis::Lock.new(:test_lock2, :expiration => 0.1)
|
661
750
|
|
662
751
|
lock.lock do
|
663
|
-
REDIS_HANDLE.exists("test_lock2").should.be.true
|
664
|
-
sleep 0
|
665
|
-
REDIS_HANDLE.exists("test_lock2").should.be.false
|
752
|
+
REDIS_HANDLE.exists?("test_lock2").should.be.true
|
753
|
+
sleep 1.0 # expired, key is deleted
|
754
|
+
REDIS_HANDLE.exists?("test_lock2").should.be.false
|
666
755
|
REDIS_HANDLE.set("test_lock2", "foo") # this is no longer a lock key, name is a coincidence
|
667
756
|
end
|
668
757
|
|
@@ -670,17 +759,17 @@ describe Redis::Lock do
|
|
670
759
|
end
|
671
760
|
|
672
761
|
it "should manually delete the key if finished before expiration" do
|
673
|
-
lock = Redis::Lock.new(:test_lock3, :expiration => 0
|
762
|
+
lock = Redis::Lock.new(:test_lock3, :expiration => 10.0)
|
674
763
|
|
675
764
|
lock.lock do
|
676
|
-
REDIS_HANDLE.exists("test_lock3").should.be.true
|
765
|
+
REDIS_HANDLE.exists?("test_lock3").should.be.true
|
677
766
|
sleep 0.1
|
678
|
-
REDIS_HANDLE.exists("test_lock3").should.be.true
|
767
|
+
REDIS_HANDLE.exists?("test_lock3").should.be.true
|
679
768
|
end
|
680
769
|
|
681
|
-
# should delete the key because the lock block is done, regardless of
|
770
|
+
# should delete the key because the lock block is done, regardless of expiry
|
682
771
|
# for some strange reason, I have seen this test fail randomly, which is worrisome.
|
683
|
-
|
772
|
+
REDIS_HANDLE.exists?("test_lock3").should.be.false
|
684
773
|
end
|
685
774
|
|
686
775
|
|
@@ -900,6 +989,13 @@ describe Redis::HashKey do
|
|
900
989
|
hsh['foo'].should == 'bar'
|
901
990
|
end
|
902
991
|
|
992
|
+
it "should return multiple items via bulk_values" do
|
993
|
+
@hash['taco'] = 42
|
994
|
+
@hash['burrito'] = 99
|
995
|
+
res = @hash.bulk_values('taco', 'burrito')
|
996
|
+
res.should == ['42', '99'] # hashes don't convert
|
997
|
+
end
|
998
|
+
|
903
999
|
it "should increment field" do
|
904
1000
|
@hash.incr('counter')
|
905
1001
|
@hash.incr('counter')
|
@@ -1007,7 +1103,9 @@ describe Redis::Set do
|
|
1007
1103
|
|
1008
1104
|
it "should handle sets of simple values" do
|
1009
1105
|
@set.should.be.empty
|
1010
|
-
@set << 'a'
|
1106
|
+
@set << 'a'
|
1107
|
+
@set.randmember.should == 'a'
|
1108
|
+
@set << 'a' << 'a'
|
1011
1109
|
@set.should == ['a']
|
1012
1110
|
@set.to_s.should == 'a'
|
1013
1111
|
@set.get.should == ['a']
|
@@ -1048,11 +1146,13 @@ describe Redis::Set do
|
|
1048
1146
|
coll = @set.select{|st| st == 'c'}
|
1049
1147
|
coll.should == ['c']
|
1050
1148
|
@set.sort.should == ['a','b','c']
|
1149
|
+
@set.randmember.should.not == 'd'
|
1051
1150
|
@set.delete_if{|m| m == 'c'}
|
1052
1151
|
@set.sort.should == ['a','b']
|
1053
1152
|
|
1054
1153
|
@set << nil
|
1055
1154
|
@set.include?("").should.be.true
|
1155
|
+
@set.sort.should == ['','a','b']
|
1056
1156
|
end
|
1057
1157
|
|
1058
1158
|
it "should handle empty array adds" do
|
@@ -1168,6 +1268,12 @@ describe Redis::Set do
|
|
1168
1268
|
@set_1.value.should == ['a']
|
1169
1269
|
end
|
1170
1270
|
|
1271
|
+
it "should support moving between sets" do
|
1272
|
+
@set_1 << 'X' << 'Y' << 'Z'
|
1273
|
+
@set_1.move('X', @set_2)
|
1274
|
+
@set_2.should == ['X']
|
1275
|
+
end
|
1276
|
+
|
1171
1277
|
it "should respond to #to_json" do
|
1172
1278
|
@set_1 << 'a'
|
1173
1279
|
JSON.parse(@set_1.to_json)['value'].should == ['a']
|
@@ -1267,6 +1373,9 @@ describe Redis::SortedSet do
|
|
1267
1373
|
@set.to_s.should == 'a, b'
|
1268
1374
|
@set.should == ['a','b']
|
1269
1375
|
@set.members.should == ['a','b']
|
1376
|
+
@set.member?('a').should == true
|
1377
|
+
@set.member?('b').should == true
|
1378
|
+
@set.member?('c').should == false
|
1270
1379
|
@set['d'] = 0
|
1271
1380
|
|
1272
1381
|
@set.rangebyscore(0, 4).should == ['d','a']
|
@@ -1316,6 +1425,10 @@ describe Redis::SortedSet do
|
|
1316
1425
|
|
1317
1426
|
@set.delete_if{|m| m == 'b'}
|
1318
1427
|
@set.size.should == 3
|
1428
|
+
|
1429
|
+
# this is destructive so must come last
|
1430
|
+
res = @set.remrangebyrank(0, 2)
|
1431
|
+
res.should == 3
|
1319
1432
|
end
|
1320
1433
|
|
1321
1434
|
it "should handle inserting multiple values at once" do
|