resque-lonely_job 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,7 +6,7 @@ module Resque
6
6
  LOCK_TIMEOUT = 60 * 60 * 24 * 5 # 5 days
7
7
 
8
8
  def lock_timeout
9
- Time.now.utc + LOCK_TIMEOUT + 1
9
+ Time.now.to_i + LOCK_TIMEOUT + 1
10
10
  end
11
11
 
12
12
  # Overwrite this method to uniquely identify which mutex should be used
@@ -16,7 +16,15 @@ module Resque
16
16
  end
17
17
 
18
18
  def can_lock_queue?(*args)
19
- Resque.redis.setnx(redis_key(*args), lock_timeout)
19
+ now = Time.now.to_i
20
+ key = redis_key(*args)
21
+ timeout = lock_timeout
22
+
23
+ # Per http://redis.io/commands/setnx
24
+ return true if Resque.redis.setnx(key, timeout)
25
+ return false if Resque.redis.get(key).to_i > now
26
+ return true if Resque.redis.getset(key, timeout).to_i <= now
27
+ return false
20
28
  end
21
29
 
22
30
  def unlock_queue(*args)
@@ -1,7 +1,7 @@
1
1
  module Resque
2
2
  module Plugins
3
3
  module LonelyJob
4
- VERSION = "0.0.3"
4
+ VERSION = "0.0.4"
5
5
  end
6
6
  end
7
7
  end
@@ -14,11 +14,12 @@ Gem::Specification.new do |gem|
14
14
  gem.require_paths = ["lib"]
15
15
  gem.version = Resque::Plugins::LonelyJob::VERSION
16
16
 
17
- gem.add_dependency 'resque', '~> 1.20.0'
17
+ gem.add_dependency 'resque', '>= 1.20.0'
18
18
  gem.add_development_dependency 'mock_redis', '~> 0.4.1'
19
19
  gem.add_development_dependency 'rake'
20
20
  gem.add_development_dependency 'rspec'
21
21
  gem.add_development_dependency 'debugger'
22
+ gem.add_development_dependency 'timecop'
22
23
 
23
24
  gem.description = <<desc
24
25
  Ensures that for a given queue, only one worker is working on a job at any given time.
@@ -32,6 +32,37 @@ describe Resque::Plugins::LonelyJob do
32
32
  SerialJob.can_lock_queue?(:serial_work).should be_true
33
33
  SerialJob.can_lock_queue?(:serial_work).should be_false
34
34
  end
35
+
36
+ it 'cannot lock a queue with active lock' do
37
+ SerialJob.can_lock_queue?(:serial_work).should be_true
38
+ Timecop.travel(Date.today + 1) do
39
+ SerialJob.can_lock_queue?(:serial_work).should be_false
40
+ end
41
+ end
42
+
43
+ it 'can relock a queue with expired lock' do
44
+ SerialJob.can_lock_queue?(:serial_work).should be_true
45
+
46
+ Timecop.travel(Date.today + 10) do
47
+ SerialJob.can_lock_queue?(:serial_work).should be_true
48
+ end
49
+ end
50
+
51
+ it 'solves race condition with getset' do
52
+ SerialJob.can_lock_queue?(:serial_work).should be_true
53
+
54
+ Timecop.travel(Date.today + 10) do
55
+ threads = (1..10).to_a.map {
56
+ Thread.new {
57
+ Thread.current[:locked] = SerialJob.can_lock_queue?(:serial_work)
58
+ }
59
+ }
60
+
61
+ # Only one worker should acquire lock
62
+ locks = threads.map {|t| t.join; t[:locked] }
63
+ locks.count(true).should == 1
64
+ end
65
+ end
35
66
  end
36
67
 
37
68
  describe ".perform" do
@@ -5,6 +5,7 @@ require 'rspec'
5
5
  require 'mock_redis'
6
6
  require 'resque'
7
7
  require 'resque-lonely_job'
8
+ require 'timecop'
8
9
 
9
10
  RSpec.configure do |config|
10
11
  config.before(:suite) do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: resque-lonely_job
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,22 +9,27 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-14 00:00:00.000000000 Z
12
+ date: 2013-01-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: resque
16
- requirement: &70264194773380 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - ~>
19
+ - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
21
  version: 1.20.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70264194773380
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.20.0
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: mock_redis
27
- requirement: &70264194772640 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ~>
@@ -32,10 +37,15 @@ dependencies:
32
37
  version: 0.4.1
33
38
  type: :development
34
39
  prerelease: false
35
- version_requirements: *70264194772640
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 0.4.1
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: rake
38
- requirement: &70264194772020 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
51
  - - ! '>='
@@ -43,10 +53,15 @@ dependencies:
43
53
  version: '0'
44
54
  type: :development
45
55
  prerelease: false
46
- version_requirements: *70264194772020
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: rspec
49
- requirement: &70264194771040 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
50
65
  none: false
51
66
  requirements:
52
67
  - - ! '>='
@@ -54,10 +69,31 @@ dependencies:
54
69
  version: '0'
55
70
  type: :development
56
71
  prerelease: false
57
- version_requirements: *70264194771040
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
58
78
  - !ruby/object:Gem::Dependency
59
79
  name: debugger
60
- requirement: &70264194768800 !ruby/object:Gem::Requirement
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: timecop
96
+ requirement: !ruby/object:Gem::Requirement
61
97
  none: false
62
98
  requirements:
63
99
  - - ! '>='
@@ -65,7 +101,12 @@ dependencies:
65
101
  version: '0'
66
102
  type: :development
67
103
  prerelease: false
68
- version_requirements: *70264194768800
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
69
110
  description: ! "Ensures that for a given queue, only one worker is working on a job
70
111
  at any given time.\n\nExample:\n\n require 'resque/plugins/lonely_job'\n\n class
71
112
  StrictlySerialJob\n extend Resque::Plugins::LonelyJob\n\n @queue = :serial_work\n\n
@@ -99,15 +140,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
99
140
  - - ! '>='
100
141
  - !ruby/object:Gem::Version
101
142
  version: '0'
143
+ segments:
144
+ - 0
145
+ hash: 610459578686015102
102
146
  required_rubygems_version: !ruby/object:Gem::Requirement
103
147
  none: false
104
148
  requirements:
105
149
  - - ! '>='
106
150
  - !ruby/object:Gem::Version
107
151
  version: '0'
152
+ segments:
153
+ - 0
154
+ hash: 610459578686015102
108
155
  requirements: []
109
156
  rubyforge_project:
110
- rubygems_version: 1.8.17
157
+ rubygems_version: 1.8.24
111
158
  signing_key:
112
159
  specification_version: 3
113
160
  summary: A resque plugin that ensures that only one job for a given queue will be
@@ -115,4 +162,3 @@ summary: A resque plugin that ensures that only one job for a given queue will b
115
162
  test_files:
116
163
  - spec/lib/lonely_job_spec.rb
117
164
  - spec/spec_helper.rb
118
- has_rdoc: