resque-lock 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/lib/resque/plugins/lock.rb +24 -1
  2. data/test/lock_test.rb +20 -0
  3. metadata +24 -55
@@ -41,6 +41,14 @@ module Resque
41
41
  # repo_id. Normally a job is locked using a combination of its
42
42
  # class name and arguments.
43
43
  module Lock
44
+
45
+ # Override in your job to control the lock experiation time. This is the
46
+ # time in seconds that the lock should be considered valid. The default
47
+ # is one hour (3600 seconds).
48
+ def lock_timeout
49
+ 3600
50
+ end
51
+
44
52
  # Override in your job to control the lock key. It is
45
53
  # passed the same arguments as `perform`, that is, your job's
46
54
  # payload.
@@ -48,8 +56,23 @@ module Resque
48
56
  "lock:#{name}-#{args.to_s}"
49
57
  end
50
58
 
59
+ # See the documentation for SETNX http://redis.io/commands/setnx for an
60
+ # explanation of this deadlock free locking pattern
51
61
  def before_enqueue_lock(*args)
52
- Resque.redis.setnx(lock(*args), true)
62
+ key = lock(*args)
63
+ now = Time.now.to_i
64
+ timeout = now + lock_timeout + 1
65
+
66
+ # return true if we successfully acquired the lock
67
+ return true if Resque.redis.setnx(key, timeout)
68
+
69
+ # see if the existing timeout is still valid and return false if it is
70
+ # (we cannot acquire the lock during the timeout period)
71
+ return false if now <= Resque.redis.get(key).to_i
72
+
73
+ # otherwise set the timeout and ensure that no other worker has
74
+ # acquired the lock
75
+ now > Resque.redis.getset(key, timeout).to_i
53
76
  end
54
77
 
55
78
  def around_perform_lock(*args)
@@ -9,6 +9,10 @@ class LockTest < Test::Unit::TestCase
9
9
  extend Resque::Plugins::Lock
10
10
  @queue = :lock_test
11
11
 
12
+ def self.lock_timeout
13
+ 1
14
+ end
15
+
12
16
  def self.perform
13
17
  raise "Woah woah woah, that wasn't supposed to happen"
14
18
  end
@@ -37,4 +41,20 @@ class LockTest < Test::Unit::TestCase
37
41
 
38
42
  assert_equal 1, Resque.redis.llen('queue:lock_test')
39
43
  end
44
+
45
+ def test_deadlock
46
+ now = Time.now.to_i
47
+
48
+ Resque.redis.set(Job.lock, now+60)
49
+ Resque.enqueue(Job)
50
+ assert_equal 0, Resque.redis.llen('queue:lock_test')
51
+
52
+ Resque.redis.set(Job.lock, now-1)
53
+ Resque.enqueue(Job)
54
+ assert_equal 1, Resque.redis.llen('queue:lock_test')
55
+
56
+ sleep 3
57
+ Resque.enqueue(Job)
58
+ assert_equal 2, Resque.redis.llen('queue:lock_test')
59
+ end
40
60
  end
metadata CHANGED
@@ -1,85 +1,54 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: resque-lock
3
- version: !ruby/object:Gem::Version
4
- hash: 23
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
5
  prerelease:
6
- segments:
7
- - 1
8
- - 0
9
- - 0
10
- version: 1.0.0
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Chris Wanstrath
14
9
  - Ray Krueger
15
10
  autorequire:
16
11
  bindir: bin
17
12
  cert_chain: []
18
-
19
- date: 2011-08-18 00:00:00 -07:00
20
- default_executable:
13
+ date: 2012-11-08 00:00:00.000000000 Z
21
14
  dependencies: []
22
-
23
- description: |
24
- A Resque plugin. If you want only one instance of your job
25
- queued at a time, extend it with this module.
26
-
27
- For example:
28
-
29
- class UpdateNetworkGraph
30
- extend Resque::Jobs::Locked
31
-
32
- def self.perform(repo_id)
33
- heavy_lifting
34
- end
35
- end
36
-
15
+ description: ! "A Resque plugin. If you want only one instance of your job\nqueued
16
+ at a time, extend it with this module.\n\nFor example:\n\n class UpdateNetworkGraph\n
17
+ \ extend Resque::Jobs::Locked\n\n def self.perform(repo_id)\n heavy_lifting\n
18
+ \ end\n end\n"
37
19
  email: chris@ozmm.org
38
20
  executables: []
39
-
40
21
  extensions: []
41
-
42
22
  extra_rdoc_files: []
43
-
44
- files:
23
+ files:
45
24
  - README.md
46
25
  - Rakefile
47
26
  - LICENSE
48
27
  - lib/resque/plugins/lock.rb
49
28
  - test/lock_test.rb
50
- has_rdoc: true
51
29
  homepage: http://github.com/defunkt/resque-lock
52
30
  licenses: []
53
-
54
31
  post_install_message:
55
32
  rdoc_options: []
56
-
57
- require_paths:
33
+ require_paths:
58
34
  - lib
59
- required_ruby_version: !ruby/object:Gem::Requirement
35
+ required_ruby_version: !ruby/object:Gem::Requirement
60
36
  none: false
61
- requirements:
62
- - - ">="
63
- - !ruby/object:Gem::Version
64
- hash: 3
65
- segments:
66
- - 0
67
- version: "0"
68
- required_rubygems_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
42
  none: false
70
- requirements:
71
- - - ">="
72
- - !ruby/object:Gem::Version
73
- hash: 3
74
- segments:
75
- - 0
76
- version: "0"
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
77
47
  requirements: []
78
-
79
48
  rubyforge_project:
80
- rubygems_version: 1.5.2
49
+ rubygems_version: 1.8.23
81
50
  signing_key:
82
51
  specification_version: 3
83
- summary: A Resque plugin for ensuring only one instance of your job is queued at a time.
52
+ summary: A Resque plugin for ensuring only one instance of your job is queued at a
53
+ time.
84
54
  test_files: []
85
-