redis_support 0.0.6 → 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- 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
|