resque-lock-timeout 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/HISTORY.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 0.3.0 (2011-07-16)
2
+
3
+ * Ability to customize redis connection used for storing locks.
4
+ (thanks Richie Vos =))
5
+ * Added Bundler `Gemfile`.
6
+ * Added abstract stub methods for callback methods:
7
+ `lock_failed`, `lock_expired_before_release`
8
+
1
9
  ## 0.2.1 (2010-06-16)
2
10
 
3
11
  * Relax gemspec dependancies.
@@ -5,4 +13,4 @@
5
13
  ## 0.2.0 (2010-05-05)
6
14
 
7
15
  * Initial release as `resque-lock-timeout`, forked from Chris Wanstrath'
8
- `resque-lock`.
16
+ `resque-lock`.
data/README.md CHANGED
@@ -92,6 +92,24 @@ repo_id.
92
92
 
93
93
  It's lock key would be: `resque-lock-timeout:UpdateNetworkGraph`.
94
94
 
95
+ ### Redis Connection Used for Locking
96
+
97
+ By default all locks are stored via Resque's redis connection. If you wish to
98
+ change this you may override `lock_redis`.
99
+
100
+ class UpdateNetworkGraph
101
+ extend Resque::Plugins::LockTimeout
102
+ @queue = :network_graph
103
+
104
+ def self.lock_redis
105
+ @lock_redis ||= Redis.new
106
+ end
107
+
108
+ def self.perform(repo_id)
109
+ heavy_lifting
110
+ end
111
+ end
112
+
95
113
  ### Callbacks
96
114
 
97
115
  Several callbacks are available to override and implement your own logic, e.g.
data/Rakefile CHANGED
@@ -1,5 +1,4 @@
1
1
  require 'rake/testtask'
2
- require 'rake/rdoctask'
3
2
  require 'yard'
4
3
  require 'yard/rake/yardoc_task'
5
4
 
@@ -43,6 +43,16 @@ module Resque
43
43
  args.join('-')
44
44
  end
45
45
 
46
+ # Override to fully control the redis object used for storing
47
+ # the locks.
48
+ #
49
+ # The default is Resque.redis
50
+ #
51
+ # @return [Redis] redis object
52
+ def lock_redis
53
+ Resque.redis
54
+ end
55
+
46
56
  # Override to fully control the lock key used. It is passed
47
57
  # the job arguments.
48
58
  #
@@ -62,6 +72,27 @@ module Resque
62
72
  @lock_timeout ||= 0
63
73
  end
64
74
 
75
+ # Convenience method, not used internally.
76
+ #
77
+ # @return [Boolean] true if the job is locked by someone
78
+ def locked?(*args)
79
+ lock_redis.exists(redis_lock_key(*args))
80
+ end
81
+
82
+ # @abstract
83
+ # Hook method; called when a were unable to aquire the lock.
84
+ #
85
+ # @param [Array] args job arguments
86
+ def lock_failed(*args)
87
+ end
88
+
89
+ # @abstract
90
+ # Hook method; called when the lock expired before we released it.
91
+ #
92
+ # @param [Array] args job arguments
93
+ def lock_expired_before_release(*args)
94
+ end
95
+
65
96
  # Try to acquire a lock.
66
97
  #
67
98
  # * Returns false; when unable to acquire the lock.
@@ -76,13 +107,13 @@ module Resque
76
107
 
77
108
  unless lock_timeout > 0
78
109
  # Acquire without using a timeout.
79
- acquired = true if Resque.redis.setnx(lock_key, true)
110
+ acquired = true if lock_redis.setnx(lock_key, true)
80
111
  else
81
112
  # Acquire using the timeout algorithm.
82
113
  acquired, lock_until = acquire_lock_algorithm!(lock_key)
83
114
  end
84
115
 
85
- lock_failed(*args) if !acquired && respond_to?(:lock_failed)
116
+ lock_failed(*args) if !acquired
86
117
  lock_until && acquired ? lock_until : acquired
87
118
  end
88
119
 
@@ -94,18 +125,18 @@ module Resque
94
125
  lock_until = now + lock_timeout
95
126
  acquired = false
96
127
 
97
- return [true, lock_until] if Resque.redis.setnx(lock_key, lock_until)
128
+ return [true, lock_until] if lock_redis.setnx(lock_key, lock_until)
98
129
  # Can't acquire the lock, see if it has expired.
99
- lock_expiration = Resque.redis.get(lock_key)
130
+ lock_expiration = lock_redis.get(lock_key)
100
131
  if lock_expiration && lock_expiration.to_i < now
101
132
  # expired, try to acquire.
102
- lock_expiration = Resque.redis.getset(lock_key, lock_until)
133
+ lock_expiration = lock_redis.getset(lock_key, lock_until)
103
134
  if lock_expiration.nil? || lock_expiration.to_i < now
104
135
  acquired = true
105
136
  end
106
137
  else
107
138
  # Try once more...
108
- acquired = true if Resque.redis.setnx(lock_key, lock_until)
139
+ acquired = true if lock_redis.setnx(lock_key, lock_until)
109
140
  end
110
141
 
111
142
  [acquired, lock_until]
@@ -113,14 +144,7 @@ module Resque
113
144
 
114
145
  # Release the lock.
115
146
  def release_lock!(*args)
116
- Resque.redis.del(redis_lock_key(*args))
117
- end
118
-
119
- # Convenience method, not used internally.
120
- #
121
- # @return [Boolean] true if the job is locked by someone
122
- def locked?(*args)
123
- Resque.redis.exists(redis_lock_key(*args))
147
+ lock_redis.del(redis_lock_key(*args))
124
148
  end
125
149
 
126
150
  # Where the magic happens.
@@ -135,7 +159,7 @@ module Resque
135
159
  # used, then we need to be more careful before releasing the lock.
136
160
  unless lock_until === true
137
161
  now = Time.now.to_i
138
- if lock_until < now && respond_to?(:lock_expired_before_release)
162
+ if lock_until < now
139
163
  # Eeek! Lock expired before perform finished. Trigger callback.
140
164
  lock_expired_before_release(*args)
141
165
  return # dont relase lock.
data/test/lock_test.rb CHANGED
@@ -105,4 +105,25 @@ class LockTest < Test::Unit::TestCase
105
105
  assert_equal true, $lock_expired, 'should be set by callback method'
106
106
  assert_equal false, FastJob.locked?, 'lock should not release'
107
107
  end
108
+
109
+ def test_lock_with_specific_redis
110
+ lock_redis = Redis.new(:host => Resque.redis.client.host,
111
+ :port => Resque.redis.client.port,
112
+ :db => 'locks',
113
+ :threadsafe => true)
114
+ SpecificRedisJob.lock_redis = lock_redis
115
+ Resque.enqueue(SpecificRedisJob)
116
+
117
+ thread = Thread.new { @worker.process }
118
+
119
+ sleep 0.1
120
+ # this is nil in Resque.redis since we make no attempt to add a resque:
121
+ # prefix to the key
122
+ assert_nil Resque.redis.get('specific_redis')
123
+ assert_not_nil lock_redis.get('specific_redis')
124
+
125
+ thread.join
126
+ assert_nil lock_redis.get('specific_redis')
127
+ assert_equal 1, $success, 'job should increment success'
128
+ end
108
129
  end
data/test/redis-test.conf CHANGED
@@ -112,21 +112,4 @@ databases 16
112
112
  # Glue small output buffers together in order to send small replies in a
113
113
  # single TCP packet. Uses a bit more CPU but most of the times it is a win
114
114
  # in terms of number of queries per second. Use 'yes' if unsure.
115
- glueoutputbuf yes
116
-
117
- # Use object sharing. Can save a lot of memory if you have many common
118
- # string in your dataset, but performs lookups against the shared objects
119
- # pool so it uses more CPU and can be a bit slower. Usually it's a good
120
- # idea.
121
- #
122
- # When object sharing is enabled (shareobjects yes) you can use
123
- # shareobjectspoolsize to control the size of the pool used in order to try
124
- # object sharing. A bigger pool size will lead to better sharing capabilities.
125
- # In general you want this value to be at least the double of the number of
126
- # very common strings you have in your dataset.
127
- #
128
- # WARNING: object sharing is experimental, don't enable this feature
129
- # in production before of Redis 1.0-stable. Still please try this feature in
130
- # your development environment so that we can test it better.
131
- shareobjects no
132
- shareobjectspoolsize 1024
115
+ glueoutputbuf yes
data/test/test_jobs.rb CHANGED
@@ -59,4 +59,26 @@ class ExpireBeforeReleaseJob
59
59
  def self.lock_expired_before_release
60
60
  $lock_expired = true
61
61
  end
62
+ end
63
+
64
+ class SpecificRedisJob
65
+ extend Resque::Plugins::LockTimeout
66
+ @queue = :test
67
+
68
+ def self.lock_redis
69
+ @redis
70
+ end
71
+
72
+ def self.lock_redis=(redis)
73
+ @redis = redis
74
+ end
75
+
76
+ def self.redis_lock_key
77
+ 'specific_redis'
78
+ end
79
+
80
+ def self.perform
81
+ $success += 1
82
+ sleep 0.2
83
+ end
62
84
  end
metadata CHANGED
@@ -1,12 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: resque-lock-timeout
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 2
8
- - 1
9
- version: 0.2.1
4
+ prerelease:
5
+ version: 0.3.0
10
6
  platform: ruby
11
7
  authors:
12
8
  - Luke Antins
@@ -16,20 +12,17 @@ autorequire:
16
12
  bindir: bin
17
13
  cert_chain: []
18
14
 
19
- date: 2010-06-27 00:00:00 +01:00
15
+ date: 2011-07-16 00:00:00 +01:00
20
16
  default_executable:
21
17
  dependencies:
22
18
  - !ruby/object:Gem::Dependency
23
19
  name: resque
24
20
  prerelease: false
25
21
  requirement: &id001 !ruby/object:Gem::Requirement
22
+ none: false
26
23
  requirements:
27
24
  - - ">="
28
25
  - !ruby/object:Gem::Version
29
- segments:
30
- - 1
31
- - 8
32
- - 0
33
26
  version: 1.8.0
34
27
  type: :runtime
35
28
  version_requirements: *id001
@@ -37,11 +30,10 @@ dependencies:
37
30
  name: turn
38
31
  prerelease: false
39
32
  requirement: &id002 !ruby/object:Gem::Requirement
33
+ none: false
40
34
  requirements:
41
35
  - - ">="
42
36
  - !ruby/object:Gem::Version
43
- segments:
44
- - 0
45
37
  version: "0"
46
38
  type: :development
47
39
  version_requirements: *id002
@@ -49,14 +41,24 @@ dependencies:
49
41
  name: yard
50
42
  prerelease: false
51
43
  requirement: &id003 !ruby/object:Gem::Requirement
44
+ none: false
52
45
  requirements:
53
46
  - - ">="
54
47
  - !ruby/object:Gem::Version
55
- segments:
56
- - 0
57
48
  version: "0"
58
49
  type: :development
59
50
  version_requirements: *id003
51
+ - !ruby/object:Gem::Dependency
52
+ name: rdiscount
53
+ prerelease: false
54
+ requirement: &id004 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: "0"
60
+ type: :development
61
+ version_requirements: *id004
60
62
  description: " A Resque plugin. Adds locking, with optional timeout/deadlock handling to\n resque jobs.\n\n Using a `lock_timeout` allows you to re-aquire the lock should your worker\n fail, crash, or is otherwise unable to relase the lock.\n \n i.e. Your server unexpectedly looses power. Very handy for jobs that are\n recurring or may be retried.\n"
61
63
  email: luke@lividpenguin.com
62
64
  executables: []
@@ -86,23 +88,21 @@ rdoc_options: []
86
88
  require_paths:
87
89
  - lib
88
90
  required_ruby_version: !ruby/object:Gem::Requirement
91
+ none: false
89
92
  requirements:
90
93
  - - ">="
91
94
  - !ruby/object:Gem::Version
92
- segments:
93
- - 0
94
95
  version: "0"
95
96
  required_rubygems_version: !ruby/object:Gem::Requirement
97
+ none: false
96
98
  requirements:
97
99
  - - ">="
98
100
  - !ruby/object:Gem::Version
99
- segments:
100
- - 0
101
101
  version: "0"
102
102
  requirements: []
103
103
 
104
104
  rubyforge_project:
105
- rubygems_version: 1.3.6
105
+ rubygems_version: 1.6.2
106
106
  signing_key:
107
107
  specification_version: 3
108
108
  summary: A Resque plugin adding locking, with optional timeout/deadlock handling to resque jobs.