sidetiq 0.1.5 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
- before_script:
6
- - bundle exec rake compile
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.resolution
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
- status = redis.get(key)
137
+ next_run = (redis.get("#{key}:next") || -1).to_f
137
138
 
138
- if status.nil? || status.to_f < time.to_f
139
- time_f = time.to_f
140
- Sidekiq.logger.info "Sidetiq::Clock enqueue #{worker.name} (at: #{time_f})"
141
- redis.set(key, time_f)
142
- worker.perform_at(time)
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} #{Thread.current.inspect}"
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} #{Thread.current.inspect}"
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
- Thread.pass
165
- sleep Sidetiq.config.resolution
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
-
@@ -6,7 +6,10 @@ module Sidetiq
6
6
 
7
7
  def call(*args)
8
8
  # Restart the clock if the thread died.
9
- @clock.start! if !@clock.ticking?
9
+ if !@clock.ticking?
10
+ Sidekiq.logger.warn "Sidetiq::Clock thread died. Restarting..."
11
+ @clock.start!
12
+ end
10
13
  yield
11
14
  end
12
15
  end
@@ -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
-
@@ -5,10 +5,10 @@ module Sidetiq
5
5
  MAJOR = 0
6
6
 
7
7
  # Public: Sidetiq minor version number.
8
- MINOR = 1
8
+ MINOR = 2
9
9
 
10
10
  # Public: Sidetiq patch level.
11
- PATCH = 5
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 = "High-resolution job scheduler for Sidekiq"
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.7.0'
23
- gem.add_dependency 'ice_cube', '~> 0.9.3'
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
@@ -1,5 +1,7 @@
1
- require 'simplecov'
2
- SimpleCov.start { add_filter "/test/" }
1
+ if ENV["COVERAGE"]
2
+ require 'simplecov'
3
+ SimpleCov.start { add_filter "/test/" }
4
+ end
3
5
 
4
6
  require 'minitest/autorun'
5
7
  require 'mocha/setup'
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
@@ -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.1.5
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-02-06 00:00:00.000000000 Z
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.7.0
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.7.0
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.9.3
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.9.3
44
+ version: 0.10.0
45
45
  none: false
46
- description: High-resolution job scheduler for Sidekiq
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: High-resolution job scheduler for Sidekiq
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: