redis_support 0.0.6 → 0.0.9
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.
- data/lib/redis_support.rb +5 -1
- data/lib/redis_support/locks.rb +86 -84
- data/test/test_redis_support.rb +28 -2
- metadata +6 -6
data/lib/redis_support.rb
CHANGED
data/lib/redis_support/locks.rb
CHANGED
@@ -1,98 +1,100 @@
|
|
1
1
|
# Locking support
|
2
2
|
#
|
3
3
|
module RedisSupport
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
# Lock a block of code so it can only be accessed by one thread in
|
7
|
+
# our system at a time.
|
8
|
+
#
|
9
|
+
# See 'acquire_redis_lock' for details on parameters.
|
10
|
+
#
|
11
|
+
# Returns nothing.
|
12
|
+
def redis_lock( key_to_lock, expiration = 30, interval = 1 )
|
13
|
+
acquire_redis_lock( key_to_lock, expiration, interval )
|
14
|
+
yield
|
15
|
+
ensure
|
16
|
+
release_redis_lock( key_to_lock )
|
17
|
+
end
|
4
18
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
# interval - sleep interval for checking the lock's status.
|
43
|
-
#
|
44
|
-
# Returns nothing.
|
45
|
-
def acquire_redis_lock( key_to_lock, expiration = 30, interval = 1 )
|
46
|
-
key = lock_key( key_to_lock )
|
47
|
-
until redis.setnx key, timeout_i( expiration )
|
48
|
-
if redis.get( key ).to_i < Time.now.to_i
|
49
|
-
old_timeout = redis.getset( key, timeout_i( expiration ) ).to_i
|
50
|
-
if old_timeout < Time.now.to_i
|
51
|
-
return # got it!
|
19
|
+
# Acquire a lock on a key in our Redis database. This is a blocking
|
20
|
+
# call. It sleeps until the lock has been successfully acquired.
|
21
|
+
#
|
22
|
+
# Basic usage:
|
23
|
+
#
|
24
|
+
# acquire_redis_lock( key.my_key )
|
25
|
+
# # do some stuff on my_key
|
26
|
+
# release_redis_lock( key.my_key )
|
27
|
+
#
|
28
|
+
# Described in detail here:
|
29
|
+
#
|
30
|
+
# http://code.google.com/p/redis/wiki/SetnxCommand
|
31
|
+
#
|
32
|
+
# key_to_lock - the key to lock. the actual key for the lock in redis will
|
33
|
+
# be this value with 'lock.' prepended, which lets this whole
|
34
|
+
# acquire_lock business act like a standard ruby object or
|
35
|
+
# synchronize lock. Also it ensures that all locks in the database
|
36
|
+
# can be easily viewed using redis.keys("lock.*")
|
37
|
+
#
|
38
|
+
# expiration - the expiration for the lock, expressed as an Integer. default is
|
39
|
+
# 30 seconds from when the lock is acquired. Note that this is the
|
40
|
+
# amount of time others will wait for you, not the amount of time
|
41
|
+
# you will wait to acquire the lock.
|
42
|
+
#
|
43
|
+
# interval - sleep interval for checking the lock's status.
|
44
|
+
#
|
45
|
+
# Returns nothing.
|
46
|
+
def acquire_redis_lock( key_to_lock, expiration = 30, interval = 1 )
|
47
|
+
key = lock_key( key_to_lock )
|
48
|
+
until redis.setnx key, timeout_i( expiration )
|
49
|
+
if redis.get( key ).to_i < Time.now.to_i
|
50
|
+
old_timeout = redis.getset( key, timeout_i( expiration ) ).to_i
|
51
|
+
if old_timeout < Time.now.to_i
|
52
|
+
return # got it!
|
53
|
+
end
|
54
|
+
else
|
55
|
+
sleep interval
|
52
56
|
end
|
53
|
-
else
|
54
|
-
sleep interval
|
55
57
|
end
|
56
58
|
end
|
57
|
-
end
|
58
59
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
60
|
+
# Acquire a redis lock only if it can be acquired
|
61
|
+
# is a nonblocking action
|
62
|
+
#
|
63
|
+
# Returns true on success and false on failure
|
64
|
+
def acquire_redis_lock_nonblock( key_to_lock, expiration = 30 )
|
65
|
+
key = lock_key( key_to_lock )
|
66
|
+
redis.setnx key, timeout_i( expiration )
|
67
|
+
end
|
68
|
+
|
69
|
+
# See docs for acquire_redis_lock above
|
70
|
+
#
|
71
|
+
# Returns nothing.
|
72
|
+
def release_redis_lock( locked_key )
|
73
|
+
redis.del lock_key( locked_key )
|
74
|
+
end
|
74
75
|
|
75
|
-
|
76
|
-
|
77
|
-
|
76
|
+
def has_redis_lock?( locked_key )
|
77
|
+
redis.exists lock_key(locked_key)
|
78
|
+
end
|
78
79
|
|
79
|
-
|
80
|
+
private
|
80
81
|
|
81
|
-
|
82
|
-
|
83
|
-
|
82
|
+
def lock_key( key_to_lock )
|
83
|
+
"lock.#{key_to_lock}"
|
84
|
+
end
|
84
85
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
86
|
+
# Converts an Integer number of seconds into a future timestamp that
|
87
|
+
# can be used with Redis.
|
88
|
+
#
|
89
|
+
# Examples
|
90
|
+
#
|
91
|
+
# timeout_i(expiration)
|
92
|
+
# # => 1274955869
|
93
|
+
#
|
94
|
+
# Returns the timestamp.
|
95
|
+
def timeout_i( timeout )
|
96
|
+
timeout.seconds.from_now.to_i
|
97
|
+
end
|
97
98
|
|
99
|
+
end
|
98
100
|
end
|
data/test/test_redis_support.rb
CHANGED
@@ -52,8 +52,13 @@ context "Redis Support" do
|
|
52
52
|
end
|
53
53
|
|
54
54
|
test "redis keys are not created if the keyname was previously used" do
|
55
|
-
assert_raise(RedisSupport::DuplicateRedisKeyDefinitionError) do
|
56
|
-
|
55
|
+
# assert_raise(RedisSupport::DuplicateRedisKeyDefinitionError) do
|
56
|
+
# TestClass.redis_key :test_var, "this:should:fail"
|
57
|
+
# end
|
58
|
+
|
59
|
+
# we are currently not using this feature
|
60
|
+
assert_nothing_raised do
|
61
|
+
TestClass.redis_key :test_var, "this:shouldnot:fail:anymore"
|
57
62
|
end
|
58
63
|
end
|
59
64
|
|
@@ -113,3 +118,24 @@ context "Including Redis Support" do
|
|
113
118
|
end
|
114
119
|
end
|
115
120
|
end
|
121
|
+
|
122
|
+
|
123
|
+
context "Including Redis Support in Module" do
|
124
|
+
setup do
|
125
|
+
RedisSupport.redis = Redis.new(:port => 9999, :host => "localhost")
|
126
|
+
|
127
|
+
module FooBar
|
128
|
+
include RedisSupport
|
129
|
+
extend self
|
130
|
+
|
131
|
+
redis_key :tester, "testing:include"
|
132
|
+
end
|
133
|
+
|
134
|
+
FooBar.redis = "localhost:1234"
|
135
|
+
end
|
136
|
+
|
137
|
+
test "the include of RedisSupport in a module" do
|
138
|
+
assert_equal 1234, FooBar.redis.client.port
|
139
|
+
assert_equal 9999, RedisSupport.redis.client.port
|
140
|
+
end
|
141
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis_support
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 13
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 9
|
10
|
+
version: 0.0.9
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Brian P O'Rourke
|
@@ -16,12 +16,10 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2010-06-
|
19
|
+
date: 2010-06-24 00:00:00 -07:00
|
20
20
|
default_executable:
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
23
|
-
name: redis
|
24
|
-
prerelease: false
|
25
23
|
requirement: &id001 !ruby/object:Gem::Requirement
|
26
24
|
none: false
|
27
25
|
requirements:
|
@@ -34,6 +32,8 @@ dependencies:
|
|
34
32
|
- 4
|
35
33
|
version: 1.0.4
|
36
34
|
type: :runtime
|
35
|
+
name: redis
|
36
|
+
prerelease: false
|
37
37
|
version_requirements: *id001
|
38
38
|
description: "Module for adding redis functionality to classes: simple key namespacing and locking and connections"
|
39
39
|
email: dolores@doloreslabs.com
|