sidetiq 0.1.5 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +10 -2
- data/CHANGELOG.md +12 -0
- data/lib/sidetiq/clock.rb +26 -13
- data/lib/sidetiq/middleware.rb +4 -1
- data/lib/sidetiq/schedulable.rb +16 -1
- data/lib/sidetiq/version.rb +2 -2
- data/sidetiq.gemspec +3 -3
- data/test/helper.rb +4 -2
- data/test/test_clock.rb +71 -2
- data/test/test_worker.rb +25 -0
- metadata +10 -8
data/.travis.yml
CHANGED
@@ -1,6 +1,14 @@
|
|
1
1
|
language: ruby
|
2
|
+
before_script:
|
3
|
+
- bundle exec rake compile
|
2
4
|
rvm:
|
5
|
+
- 1.9.2
|
3
6
|
- 1.9.3
|
4
7
|
- 2.0.0
|
5
|
-
|
6
|
-
-
|
8
|
+
- ruby-head
|
9
|
+
- jruby-19mode
|
10
|
+
- rbx-19mode
|
11
|
+
matrix:
|
12
|
+
allow_failures:
|
13
|
+
- rvm: 1.9.2
|
14
|
+
- rvm: jruby-19mode
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
0.2.0
|
2
|
+
-----
|
3
|
+
|
4
|
+
- Add class methods to get last and next scheduled occurrence.
|
5
|
+
- Pass last and next (current) occurrence to #perform, if desired.
|
6
|
+
This checks the method arity of #perform.
|
7
|
+
- Bump Sidekiq dependency to 2.8.0
|
8
|
+
- Fix incorrectly assigned Thread priority.
|
9
|
+
- Adjust clock sleep depending of execution time of the last tick.
|
10
|
+
- Don't log thread object ids.
|
11
|
+
- Issue a warning from the middleware if the clock thread died previously.
|
12
|
+
|
1
13
|
0.1.5
|
2
14
|
-----
|
3
15
|
|
data/lib/sidetiq/clock.rb
CHANGED
@@ -92,7 +92,7 @@ module Sidetiq
|
|
92
92
|
Sidekiq.logger.info "Sidetiq::Clock start"
|
93
93
|
@thread = Thread.start { clock { tick } }
|
94
94
|
@thread.abort_on_exception = true
|
95
|
-
@thread.priority = Sidetiq.config.
|
95
|
+
@thread.priority = Sidetiq.config.priority
|
96
96
|
@thread
|
97
97
|
end
|
98
98
|
|
@@ -131,15 +131,20 @@ module Sidetiq
|
|
131
131
|
|
132
132
|
def enqueue(worker, time)
|
133
133
|
key = "sidetiq:#{worker.name}"
|
134
|
+
time_f = time.to_f
|
134
135
|
|
135
136
|
synchronize_clockworks("#{key}:lock") do |redis|
|
136
|
-
|
137
|
+
next_run = (redis.get("#{key}:next") || -1).to_f
|
137
138
|
|
138
|
-
if
|
139
|
-
time_f
|
140
|
-
|
141
|
-
redis.
|
142
|
-
|
139
|
+
if next_run < time_f
|
140
|
+
Sidekiq.logger.info "Sidetiq::Clock enqueue #{worker.name} (at: #{time_f}) (last: #{next_run})"
|
141
|
+
|
142
|
+
redis.mset("#{key}:last", next_run, "#{key}:next", time_f)
|
143
|
+
|
144
|
+
arity = [worker.instance_method(:perform).arity - 1, -1].max
|
145
|
+
args = [next_run, time_f][0..arity]
|
146
|
+
|
147
|
+
worker.perform_at(time, *args)
|
143
148
|
end
|
144
149
|
end
|
145
150
|
end
|
@@ -147,24 +152,32 @@ module Sidetiq
|
|
147
152
|
def synchronize_clockworks(lock)
|
148
153
|
Sidekiq.redis do |redis|
|
149
154
|
if redis.setnx(lock, 1)
|
150
|
-
Sidekiq.logger.debug "Sidetiq::Clock lock #{lock}
|
155
|
+
Sidekiq.logger.debug "Sidetiq::Clock lock #{lock}"
|
151
156
|
|
152
157
|
redis.pexpire(lock, Sidetiq.config.lock_expire)
|
153
158
|
yield redis
|
154
159
|
redis.del(lock)
|
155
160
|
|
156
|
-
Sidekiq.logger.debug "Sidetiq::Clock unlock #{lock}
|
161
|
+
Sidekiq.logger.debug "Sidetiq::Clock unlock #{lock}"
|
157
162
|
end
|
158
163
|
end
|
159
164
|
end
|
160
165
|
|
161
166
|
def clock
|
162
167
|
loop do
|
163
|
-
yield
|
164
|
-
|
165
|
-
|
168
|
+
sleep_time = time { yield }
|
169
|
+
|
170
|
+
if sleep_time > 0
|
171
|
+
Thread.pass
|
172
|
+
sleep sleep_time
|
173
|
+
end
|
166
174
|
end
|
167
175
|
end
|
176
|
+
|
177
|
+
def time
|
178
|
+
start = gettime
|
179
|
+
yield
|
180
|
+
Sidetiq.config.resolution - (gettime.to_f - start.to_f)
|
181
|
+
end
|
168
182
|
end
|
169
183
|
end
|
170
|
-
|
data/lib/sidetiq/middleware.rb
CHANGED
data/lib/sidetiq/schedulable.rb
CHANGED
@@ -12,12 +12,28 @@ module Sidetiq
|
|
12
12
|
# end
|
13
13
|
module Schedulable
|
14
14
|
module ClassMethods
|
15
|
+
def last_scheduled_occurrence
|
16
|
+
get_timestamp "last"
|
17
|
+
end
|
18
|
+
|
19
|
+
def next_scheduled_occurrence
|
20
|
+
get_timestamp "next"
|
21
|
+
end
|
22
|
+
|
15
23
|
def tiq(&block) # :nodoc:
|
16
24
|
clock = Sidetiq::Clock.instance
|
17
25
|
clock.synchronize do
|
18
26
|
clock.schedule_for(self).instance_eval(&block)
|
19
27
|
end
|
20
28
|
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def get_timestamp(key)
|
33
|
+
Sidekiq.redis do |redis|
|
34
|
+
(redis.get("sidetiq:#{name}:#{key}") || -1).to_f
|
35
|
+
end
|
36
|
+
end
|
21
37
|
end
|
22
38
|
|
23
39
|
def self.included(klass) # :nodoc:
|
@@ -25,4 +41,3 @@ module Sidetiq
|
|
25
41
|
end
|
26
42
|
end
|
27
43
|
end
|
28
|
-
|
data/lib/sidetiq/version.rb
CHANGED
@@ -5,10 +5,10 @@ module Sidetiq
|
|
5
5
|
MAJOR = 0
|
6
6
|
|
7
7
|
# Public: Sidetiq minor version number.
|
8
|
-
MINOR =
|
8
|
+
MINOR = 2
|
9
9
|
|
10
10
|
# Public: Sidetiq patch level.
|
11
|
-
PATCH =
|
11
|
+
PATCH = 0
|
12
12
|
|
13
13
|
# Public: String representation of the current Sidetiq version.
|
14
14
|
STRING = [MAJOR, MINOR, PATCH].compact.join('.')
|
data/sidetiq.gemspec
CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |gem|
|
|
8
8
|
gem.version = Sidetiq::VERSION::STRING
|
9
9
|
gem.authors = ["Tobias Svensson"]
|
10
10
|
gem.email = ["tob@tobiassvensson.co.uk"]
|
11
|
-
gem.description = "
|
11
|
+
gem.description = "Recurring jobs for Sidekiq"
|
12
12
|
gem.summary = gem.description
|
13
13
|
gem.homepage = "http://github.com/tobiassvn/sidetiq"
|
14
14
|
gem.license = "MIT"
|
@@ -19,6 +19,6 @@ Gem::Specification.new do |gem|
|
|
19
19
|
gem.require_paths = ["lib"]
|
20
20
|
gem.extensions = ['ext/sidetiq_ext/extconf.rb']
|
21
21
|
|
22
|
-
gem.add_dependency 'sidekiq', '~> 2.
|
23
|
-
gem.add_dependency 'ice_cube', '~> 0.
|
22
|
+
gem.add_dependency 'sidekiq', '~> 2.8.0'
|
23
|
+
gem.add_dependency 'ice_cube', '~> 0.10.0'
|
24
24
|
end
|
data/test/helper.rb
CHANGED
data/test/test_clock.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
require_relative 'helper'
|
2
2
|
|
3
3
|
class TestClock < Sidetiq::TestCase
|
4
|
-
class FakeWorker
|
4
|
+
class FakeWorker
|
5
|
+
def perform
|
6
|
+
end
|
5
7
|
end
|
6
8
|
|
7
9
|
def test_delegates_to_instance
|
@@ -61,5 +63,72 @@ class TestClock < Sidetiq::TestCase
|
|
61
63
|
clock.tick
|
62
64
|
clock.tick
|
63
65
|
end
|
64
|
-
end
|
65
66
|
|
67
|
+
class LastTickWorker
|
68
|
+
def perform last_tick
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_enqueues_jobs_with_default_last_tick_arg_on_first_run
|
73
|
+
schedule = Sidetiq::Schedule.new(Sidetiq::Clock::START_TIME)
|
74
|
+
schedule.hourly
|
75
|
+
|
76
|
+
time = Time.local(2011, 1, 1, 1, 30)
|
77
|
+
|
78
|
+
clock.stubs(:gettime).returns(time, time + 3600)
|
79
|
+
clock.stubs(:schedules).returns(LastTickWorker => schedule)
|
80
|
+
|
81
|
+
expected_first_tick = time + 1800
|
82
|
+
expected_second_tick = expected_first_tick + 3600
|
83
|
+
|
84
|
+
LastTickWorker.expects(:perform_at).with(expected_first_tick, -1).once
|
85
|
+
LastTickWorker.expects(:perform_at).with(expected_second_tick, expected_first_tick.to_f).once
|
86
|
+
|
87
|
+
clock.tick
|
88
|
+
clock.tick
|
89
|
+
end
|
90
|
+
|
91
|
+
class LastAndScheduledTicksWorker
|
92
|
+
def perform last_tick, scheduled_tick
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_enqueues_jobs_with_last_run_timestamp_and_next_run_timestamp
|
97
|
+
schedule = Sidetiq::Schedule.new(Sidetiq::Clock::START_TIME)
|
98
|
+
schedule.hourly
|
99
|
+
|
100
|
+
time = Time.local(2011, 1, 1, 1, 30)
|
101
|
+
|
102
|
+
clock.stubs(:gettime).returns(time, time + 3600)
|
103
|
+
clock.stubs(:schedules).returns(LastAndScheduledTicksWorker => schedule)
|
104
|
+
|
105
|
+
expected_first_tick = time + 1800
|
106
|
+
expected_second_tick = expected_first_tick + 3600
|
107
|
+
|
108
|
+
LastAndScheduledTicksWorker.expects(:perform_at).with(expected_first_tick, -1, expected_first_tick.to_f).once
|
109
|
+
clock.tick
|
110
|
+
|
111
|
+
LastAndScheduledTicksWorker.expects(:perform_at).with(expected_second_tick, expected_first_tick.to_f, expected_second_tick.to_f).once
|
112
|
+
clock.tick
|
113
|
+
end
|
114
|
+
|
115
|
+
class SplatArgsWorker
|
116
|
+
def perform arg1, *args
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_enqueues_jobs_correctly_for_splat_args_perform_methods
|
121
|
+
schedule = Sidetiq::Schedule.new(Sidetiq::Clock::START_TIME)
|
122
|
+
schedule.hourly
|
123
|
+
|
124
|
+
time = Time.local(2011, 1, 1, 1, 30)
|
125
|
+
|
126
|
+
clock.stubs(:gettime).returns(time, time + 3600)
|
127
|
+
clock.stubs(:schedules).returns(SplatArgsWorker => schedule)
|
128
|
+
|
129
|
+
expected_first_tick = time + 1800
|
130
|
+
|
131
|
+
SplatArgsWorker.expects(:perform_at).with(expected_first_tick, -1, expected_first_tick.to_f).once
|
132
|
+
clock.tick
|
133
|
+
end
|
134
|
+
end
|
data/test/test_worker.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require_relative 'helper'
|
2
|
+
|
3
|
+
class TestWorker < Sidetiq::TestCase
|
4
|
+
class FakeWorker
|
5
|
+
include Sidetiq::Schedulable
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_timestamps_for_new_worker
|
9
|
+
assert FakeWorker.last_scheduled_occurrence == -1
|
10
|
+
assert FakeWorker.next_scheduled_occurrence == -1
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_timestamps_for_existing_worker
|
14
|
+
last_run = (Time.now - 100).to_f
|
15
|
+
next_run = (Time.now + 100).to_f
|
16
|
+
|
17
|
+
Sidekiq.redis do |redis|
|
18
|
+
redis.set "sidetiq:TestWorker::FakeWorker:last", last_run
|
19
|
+
redis.set "sidetiq:TestWorker::FakeWorker:next", next_run
|
20
|
+
end
|
21
|
+
|
22
|
+
assert FakeWorker.last_scheduled_occurrence == last_run
|
23
|
+
assert FakeWorker.next_scheduled_occurrence == next_run
|
24
|
+
end
|
25
|
+
end
|
metadata
CHANGED
@@ -2,21 +2,21 @@
|
|
2
2
|
name: sidetiq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.2.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Tobias Svensson
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-03-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
version_requirements: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ~>
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 2.
|
19
|
+
version: 2.8.0
|
20
20
|
none: false
|
21
21
|
name: sidekiq
|
22
22
|
type: :runtime
|
@@ -25,14 +25,14 @@ dependencies:
|
|
25
25
|
requirements:
|
26
26
|
- - ~>
|
27
27
|
- !ruby/object:Gem::Version
|
28
|
-
version: 2.
|
28
|
+
version: 2.8.0
|
29
29
|
none: false
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
version_requirements: !ruby/object:Gem::Requirement
|
32
32
|
requirements:
|
33
33
|
- - ~>
|
34
34
|
- !ruby/object:Gem::Version
|
35
|
-
version: 0.
|
35
|
+
version: 0.10.0
|
36
36
|
none: false
|
37
37
|
name: ice_cube
|
38
38
|
type: :runtime
|
@@ -41,9 +41,9 @@ dependencies:
|
|
41
41
|
requirements:
|
42
42
|
- - ~>
|
43
43
|
- !ruby/object:Gem::Version
|
44
|
-
version: 0.
|
44
|
+
version: 0.10.0
|
45
45
|
none: false
|
46
|
-
description:
|
46
|
+
description: Recurring jobs for Sidekiq
|
47
47
|
email:
|
48
48
|
- tob@tobiassvensson.co.uk
|
49
49
|
executables: []
|
@@ -81,6 +81,7 @@ files:
|
|
81
81
|
- test/test_schedule.rb
|
82
82
|
- test/test_version.rb
|
83
83
|
- test/test_web.rb
|
84
|
+
- test/test_worker.rb
|
84
85
|
homepage: http://github.com/tobiassvn/sidetiq
|
85
86
|
licenses:
|
86
87
|
- MIT
|
@@ -105,7 +106,7 @@ rubyforge_project:
|
|
105
106
|
rubygems_version: 1.8.23
|
106
107
|
signing_key:
|
107
108
|
specification_version: 3
|
108
|
-
summary:
|
109
|
+
summary: Recurring jobs for Sidekiq
|
109
110
|
test_files:
|
110
111
|
- test/helper.rb
|
111
112
|
- test/test_clock.rb
|
@@ -115,4 +116,5 @@ test_files:
|
|
115
116
|
- test/test_schedule.rb
|
116
117
|
- test/test_version.rb
|
117
118
|
- test/test_web.rb
|
119
|
+
- test/test_worker.rb
|
118
120
|
has_rdoc:
|