sidetiq 0.4.0.rc2 → 0.4.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 456f6b922646c7e198b83f34b299e07f984a6c0f
4
- data.tar.gz: 3401166967dab3170b26f961147d014950e68dfe
3
+ metadata.gz: 9aef5c4cda17d14aa2592dc263cbd945d06e45de
4
+ data.tar.gz: 692bdc4bacfea9a9f641b0c947e226dd58da20f4
5
5
  SHA512:
6
- metadata.gz: 34d95105066f87aa9736bf3e4e454df16cf065f841051809f60e5f3aa1123d750fcaa317c545d6344ad6cfcb3ad199b987cb52a2ebf3ae21794ce13910485242
7
- data.tar.gz: de936682d4191d86e36e94439f97d2ce549ddd671b793eca78f1d39b33462c6e8373513cf66ec8f7b7ce5f90dcf1378b43a513745c56a61b4f50070916ffa405
6
+ metadata.gz: a4b9e85e2ce6a206e84b3f15338fc2fec527978d13b617232692cc0a0098469bf0f00d03b017e1323667681179374ab024cd5f3f3a4dac46ab04b5f458cf12ad
7
+ data.tar.gz: 91a79a02ee8718e1ea787474b12cbc94bf78ae49d3a38641511a4238902f871d5bc21e01e53091e9a3b99bd27fe359d7728b0160bf59e66426b73320f3cfacd4
data/CHANGELOG.md CHANGED
@@ -1,6 +1,8 @@
1
1
  0.4.0
2
2
  -----
3
3
 
4
+ - Schedules are now stored on the workers directly instead of in a
5
+ pseudo-global, mutable Hash.
4
6
  - Clock now start looping automatically if `Sidekiq.server?` returns true.
5
7
  - Show job history in web extension.
6
8
  - Integrate with Sidekiq's exception handling/reporting in critical parts.
data/lib/sidetiq/actor.rb CHANGED
@@ -27,8 +27,8 @@ module Sidetiq
27
27
  def link_to_sidekiq_manager
28
28
  Sidekiq::CLI.instance.launcher.manager.link(current_actor)
29
29
  rescue NoMethodError
30
- warn "Can't link #{self.class.name}. Sidekiq::Manager not running. Retrying ..."
31
- after(1) { link_to_sidekiq_manager }
30
+ warn "Can't link #{self.class.name}. Sidekiq::Manager not running. Retrying in 5 seconds ..."
31
+ after(5) { link_to_sidekiq_manager }
32
32
  end
33
33
 
34
34
  def log_call(call)
data/lib/sidetiq/api.rb CHANGED
@@ -3,12 +3,12 @@ module Sidetiq
3
3
  module API
4
4
  # Public: Returns an Array of workers including Sidetiq::Schedulable.
5
5
  def workers
6
- schedules.keys
6
+ Sidetiq::Schedulable.subclasses(true)
7
7
  end
8
8
 
9
9
  # Public: Returns a Hash of Sidetiq::Schedule instances.
10
10
  def schedules
11
- clock.schedules.dup
11
+ workers.map(&:schedule)
12
12
  end
13
13
 
14
14
  # Public: Currently scheduled recurring jobs.
data/lib/sidetiq/clock.rb CHANGED
@@ -8,7 +8,6 @@ module Sidetiq
8
8
 
9
9
  def initialize # :nodoc:
10
10
  super
11
- @schedules = {}
12
11
  end
13
12
 
14
13
  # Public: Get the schedule for `worker`.
@@ -22,7 +21,9 @@ module Sidetiq
22
21
  #
23
22
  # Returns a Sidetiq::Schedule instances.
24
23
  def schedule_for(worker)
25
- schedules[worker] ||= Sidetiq::Schedule.new
24
+ if worker.respond_to?(:schedule)
25
+ worker.schedule
26
+ end
26
27
  end
27
28
 
28
29
  # Public: Issue a single clock tick.
@@ -35,8 +36,8 @@ module Sidetiq
35
36
  # Returns a hash of Sidetiq::Schedule instances.
36
37
  def tick
37
38
  tick = gettime
38
- schedules.each do |worker, sched|
39
- Sidetiq.handler.dispatch(worker,sched, tick)
39
+ Sidetiq.workers.each do |worker|
40
+ Sidetiq.handler.dispatch(worker, tick)
40
41
  end
41
42
  end
42
43
 
@@ -3,18 +3,20 @@ module Sidetiq
3
3
  include Logging
4
4
  include Sidekiq::ExceptionHandler
5
5
 
6
- def dispatch(worker, sched, tick)
7
- return unless sched.schedule_next?(tick)
6
+ def dispatch(worker, tick)
7
+ schedule = worker.schedule
8
+
9
+ return unless schedule.schedule_next?(tick)
8
10
 
9
11
  Lock::Redis.new(worker).synchronize do |redis|
10
- if sched.backfill? && (last = worker.last_scheduled_occurrence) > 0
12
+ if schedule.backfill? && (last = worker.last_scheduled_occurrence) > 0
11
13
  last = Sidetiq.config.utc ? Time.at(last).utc : Time.at(last)
12
- sched.occurrences_between(last + 1, tick).each do |past_t|
14
+ schedule.occurrences_between(last + 1, tick).each do |past_t|
13
15
  enqueue(worker, past_t, redis)
14
16
  end
15
17
  end
16
18
 
17
- enqueue(worker, sched.next_occurrence(tick), redis)
19
+ enqueue(worker, schedule.next_occurrence(tick), redis)
18
20
  end
19
21
  rescue StandardError => e
20
22
  handle_exception(e, context: "Sidetiq::Handler#dispatch")
@@ -39,12 +39,10 @@ module Sidetiq
39
39
 
40
40
  def save_entry_for_worker(entry, worker)
41
41
  Sidekiq.redis do |redis|
42
- redis.pipelined do |pipe|
43
- list_name = "sidetiq:#{worker.class.name}:history"
42
+ list_name = "sidetiq:#{worker.class.name}:history"
44
43
 
45
- pipe.lpush(list_name, JSON.dump(entry))
46
- pipe.ltrim(list_name, 0, Sidetiq.config.worker_history - 1)
47
- end
44
+ redis.lpush(list_name, JSON.dump(entry))
45
+ redis.ltrim(list_name, 0, Sidetiq.config.worker_history - 1)
48
46
  end
49
47
  end
50
48
  end
@@ -11,14 +11,24 @@ module Sidetiq
11
11
  # recurrence { daily }
12
12
  # end
13
13
  module Schedulable
14
+ extend SubclassTracking
15
+
14
16
  module ClassMethods
15
17
  include Logging
18
+ include SubclassTracking
19
+
20
+ attr_writer :schedule
16
21
 
17
22
  # Public: Returns a Float timestamp of the last scheduled run.
18
23
  def last_scheduled_occurrence
19
24
  get_timestamp "last"
20
25
  end
21
26
 
27
+ # Public: Returns the Sidetiq::Schedule for this worker.
28
+ def schedule
29
+ @schedule ||= Sidetiq::Schedule.new
30
+ end
31
+
22
32
  # Public: Returns a Float timestamp of the next scheduled run.
23
33
  def next_scheduled_occurrence
24
34
  get_timestamp "next"
@@ -32,7 +42,6 @@ module Sidetiq
32
42
  end
33
43
 
34
44
  def recurrence(options = {}, &block) # :nodoc:
35
- schedule = Sidetiq.clock.schedule_for(self)
36
45
  schedule.instance_eval(&block)
37
46
  schedule.set_options(options)
38
47
  end
@@ -47,7 +56,11 @@ module Sidetiq
47
56
  end
48
57
 
49
58
  def self.included(klass) # :nodoc:
59
+ super
60
+
50
61
  klass.extend(Sidetiq::Schedulable::ClassMethods)
62
+ klass.extend(Sidetiq::SubclassTracking)
63
+ subclasses << klass
51
64
  end
52
65
  end
53
66
  end
@@ -0,0 +1,20 @@
1
+ module Sidetiq
2
+ module SubclassTracking
3
+ def subclasses(deep = false)
4
+ @subclasses ||= []
5
+
6
+ if deep
7
+ @subclasses.inject([]) do |all, subclass|
8
+ (all << subclass) + subclass.subclasses(true)
9
+ end
10
+ else
11
+ @subclasses
12
+ end
13
+ end
14
+
15
+ def inherited(klass)
16
+ super
17
+ subclasses << klass
18
+ end
19
+ end
20
+ end
@@ -11,7 +11,7 @@ module Sidetiq
11
11
  PATCH = 0
12
12
 
13
13
  # Public: Sidetiq version suffix.
14
- SUFFIX = 'rc2'
14
+ SUFFIX = 'rc3'
15
15
 
16
16
  # Public: String representation of the current Sidetiq version.
17
17
  STRING = [MAJOR, MINOR, PATCH, SUFFIX].compact.join('.')
@@ -1,13 +1,13 @@
1
1
  <div class="span3">
2
2
  <ul class="nav nav-list sidetiq-sidenav">
3
3
  <li>
4
- <a href="/sidetiq">
4
+ <a href="<%= " #{root_path}sidetiq" %>">
5
5
  <i class="icon-chevron-right"></i>
6
6
  Home
7
7
  </a>
8
8
  </li>
9
9
  <li>
10
- <a href="/sidetiq/locks">
10
+ <a href="<%= "#{root_path}sidetiq/locks" %>">
11
11
  <i class="icon-chevron-right"></i>
12
12
  Locks
13
13
  </a>
@@ -1,19 +1,19 @@
1
1
  <div class="span3">
2
2
  <ul class="nav nav-list sidetiq-sidenav">
3
3
  <li>
4
- <a href="/sidetiq">
4
+ <a href="<%= "#{root_path}sidetiq" %>">
5
5
  <i class="icon-chevron-right"></i>
6
6
  Home
7
7
  </a>
8
8
  </li>
9
9
  <li>
10
- <a href="/sidetiq/<%= @worker.name %>/schedule">
10
+ <a href="<%= "#{root_path}sidetiq/#{@worker.name}/schedule" %>">
11
11
  <i class="icon-chevron-right"></i>
12
12
  Job Schedule
13
13
  </a>
14
14
  </li>
15
15
  <li>
16
- <a href="/sidetiq/<%= @worker.name %>/history">
16
+ <a href="<%= "#{root_path}sidetiq/#{@worker.name}/history" %>">
17
17
  <i class="icon-chevron-right"></i>
18
18
  Job History
19
19
  </a>
@@ -11,7 +11,7 @@
11
11
  <%= erb File.read(File.join(File.dirname(__FILE__), 'views', '_home_nav.erb')) %>
12
12
 
13
13
  <div class="span9">
14
- <% if @schedules.length > 0 %>
14
+ <% if @workers.length > 0 %>
15
15
  <table class="table table-striped table-bordered table-white" style="width: 100%; margin: 0; table-layout:fixed;">
16
16
  <thead>
17
17
  <th style="width: 50%">Worker</th>
@@ -19,7 +19,8 @@
19
19
  <th style="width: 30%">Next Run</th>
20
20
  <th style="width: 10%">Actions</th>
21
21
  </thead>
22
- <% @schedules.each do |worker, schedule| %>
22
+ <% @workers.each do |worker| %>
23
+ <% schedule = worker.schedule %>
23
24
  <tr>
24
25
  <td>
25
26
  <a href="<%= "#{root_path}sidetiq/#{worker.name}/schedule" %>"><%= worker.name %></a>
data/lib/sidetiq/web.rb CHANGED
@@ -6,7 +6,7 @@ module Sidetiq
6
6
 
7
7
  def self.registered(app)
8
8
  app.get "/sidetiq" do
9
- @schedules = Sidetiq.schedules
9
+ @workers = Sidetiq.workers
10
10
  @time = Sidetiq.clock.gettime
11
11
  erb File.read(File.join(VIEWS, 'sidetiq.erb'))
12
12
  end
@@ -22,9 +22,11 @@ module Sidetiq
22
22
 
23
23
  @time = Sidetiq.clock.gettime
24
24
 
25
- @worker, @schedule = Sidetiq.schedules.select do |worker, _|
25
+ @worker = Sidetiq.workers.detect do |worker|
26
26
  worker.name == name
27
- end.flatten
27
+ end
28
+
29
+ @schedule = @worker.schedule
28
30
 
29
31
  erb File.read(File.join(VIEWS, 'schedule.erb'))
30
32
  end
@@ -34,12 +36,12 @@ module Sidetiq
34
36
 
35
37
  @time = Sidetiq.clock.gettime
36
38
 
37
- @worker, @schedule = Sidetiq.schedules.select do |worker, _|
39
+ @worker = Sidetiq.workers.detect do |worker|
38
40
  worker.name == name
39
- end.flatten
41
+ end
40
42
 
41
43
  @history = Sidekiq.redis do |redis|
42
- redis.lrange("sidetiq:#{@worker.name}:history", 0, -1)
44
+ redis.lrange("sidetiq:#{name}:history", 0, -1)
43
45
  end
44
46
 
45
47
  erb File.read(File.join(VIEWS, 'history.erb'))
@@ -48,9 +50,9 @@ module Sidetiq
48
50
  app.post "/sidetiq/:name/trigger" do
49
51
  halt 404 unless (name = params[:name])
50
52
 
51
- worker, _ = Sidetiq.schedules.select do |w, _|
52
- w.name == name
53
- end.flatten
53
+ worker = Sidetiq.workers.detect do |worker|
54
+ worker.name == name
55
+ end
54
56
 
55
57
  worker.perform_async
56
58
 
data/lib/sidetiq.rb CHANGED
@@ -2,6 +2,7 @@
2
2
  require 'ostruct'
3
3
  require 'singleton'
4
4
  require 'socket'
5
+ require 'time'
5
6
 
6
7
  # gems
7
8
  require 'ice_cube'
@@ -12,6 +13,7 @@ require 'celluloid'
12
13
  require 'sidetiq/config'
13
14
  require 'sidetiq/logging'
14
15
  require 'sidetiq/api'
16
+ require 'sidetiq/subclass_tracking'
15
17
  require 'sidetiq/clock'
16
18
  require 'sidetiq/handler'
17
19
  require 'sidetiq/lock/meta_data'
@@ -58,3 +60,7 @@ module Sidetiq
58
60
  Sidetiq::Supervisor.handler
59
61
  end
60
62
  end
63
+
64
+ if Sidekiq.server?
65
+ Sidetiq::Supervisor.run!
66
+ end
@@ -1,4 +1,9 @@
1
1
  class LastAndScheduledTicksWorker
2
+ include Sidekiq::Worker
3
+ include Sidetiq::Schedulable
4
+
5
+ recurrence { hourly }
6
+
2
7
  def perform(last_tick, scheduled_tick)
3
8
  end
4
9
  end
@@ -1,4 +1,9 @@
1
1
  class LastTickWorker
2
+ include Sidekiq::Worker
3
+ include Sidetiq::Schedulable
4
+
5
+ recurrence { hourly }
6
+
2
7
  def perform(last_tick)
3
8
  end
4
9
  end
@@ -1,7 +1,9 @@
1
1
  class OptionalArgumentWorker
2
- include Sidekiq::Worker
2
+ include Sidekiq::Worker
3
3
  include Sidetiq::Schedulable
4
4
 
5
+ recurrence { hourly }
6
+
5
7
  def perform(last_tick = nil)
6
8
  end
7
9
  end
@@ -2,6 +2,8 @@ class SimpleWorker
2
2
  include Sidekiq::Worker
3
3
  include Sidetiq::Schedulable
4
4
 
5
+ recurrence { daily }
6
+
5
7
  def perform
6
8
  end
7
9
  end
@@ -1,4 +1,9 @@
1
1
  class SplatArgsWorker
2
+ include Sidekiq::Worker
3
+ include Sidetiq::Schedulable
4
+
5
+ recurrence { hourly }
6
+
2
7
  def perform(arg1, *args)
3
8
  end
4
9
  end
data/test/test_clock.rb CHANGED
@@ -18,6 +18,7 @@ class TestClock < Sidetiq::TestCase
18
18
 
19
19
  def test_backfilling
20
20
  BackfillWorker.jobs.clear
21
+ Sidetiq.stubs(:workers).returns([BackfillWorker])
21
22
  start = Sidetiq::Schedule::START_TIME
22
23
 
23
24
  BackfillWorker.stubs(:last_scheduled_occurrence).returns(start.to_f)
@@ -32,10 +33,7 @@ class TestClock < Sidetiq::TestCase
32
33
  end
33
34
 
34
35
  def test_enqueues_jobs_by_schedule
35
- schedule = Sidetiq::Schedule.new
36
- schedule.daily
37
-
38
- clock.stubs(:schedules).returns(SimpleWorker => schedule)
36
+ Sidetiq.stubs(:workers).returns([SimpleWorker])
39
37
 
40
38
  SimpleWorker.expects(:perform_at).times(10)
41
39
 
@@ -51,13 +49,11 @@ class TestClock < Sidetiq::TestCase
51
49
  end
52
50
 
53
51
  def test_enqueues_jobs_with_default_last_tick_arg_on_first_run
54
- schedule = Sidetiq::Schedule.new
55
- schedule.hourly
56
-
57
52
  time = Time.local(2011, 1, 1, 1, 30)
58
53
 
59
54
  clock.stubs(:gettime).returns(time, time + 3600)
60
- clock.stubs(:schedules).returns(LastTickWorker => schedule)
55
+
56
+ Sidetiq.stubs(:workers).returns([LastTickWorker])
61
57
 
62
58
  expected_first_tick = time + 1800
63
59
  expected_second_tick = expected_first_tick + 3600
@@ -71,13 +67,11 @@ class TestClock < Sidetiq::TestCase
71
67
  end
72
68
 
73
69
  def test_enqueues_jobs_with_last_run_timestamp_and_next_run_timestamp
74
- schedule = Sidetiq::Schedule.new
75
- schedule.hourly
76
-
77
70
  time = Time.local(2011, 1, 1, 1, 30)
78
71
 
79
72
  clock.stubs(:gettime).returns(time, time + 3600)
80
- clock.stubs(:schedules).returns(LastAndScheduledTicksWorker => schedule)
73
+
74
+ Sidetiq.stubs(:workers).returns([LastAndScheduledTicksWorker])
81
75
 
82
76
  expected_first_tick = time + 1800
83
77
  expected_second_tick = expected_first_tick + 3600
@@ -95,13 +89,11 @@ class TestClock < Sidetiq::TestCase
95
89
  end
96
90
 
97
91
  def test_enqueues_jobs_with_last_run_timestamp_if_optional_argument
98
- schedule = Sidetiq::Schedule.new
99
- schedule.hourly
100
-
101
92
  time = Time.local(2011, 1, 1, 1, 30)
102
93
 
103
94
  clock.stubs(:gettime).returns(time, time + 3600)
104
- clock.stubs(:schedules).returns(OptionalArgumentWorker => schedule)
95
+
96
+ Sidetiq.stubs(:workers).returns([OptionalArgumentWorker])
105
97
 
106
98
  expected_first_tick = time + 1800
107
99
 
@@ -111,13 +103,11 @@ class TestClock < Sidetiq::TestCase
111
103
  end
112
104
 
113
105
  def test_enqueues_jobs_correctly_for_splat_args_perform_methods
114
- schedule = Sidetiq::Schedule.new
115
- schedule.hourly
116
-
117
106
  time = Time.local(2011, 1, 1, 1, 30)
118
107
 
119
108
  clock.stubs(:gettime).returns(time, time + 3600)
120
- clock.stubs(:schedules).returns(SplatArgsWorker => schedule)
109
+
110
+ Sidetiq.stubs(:workers).returns([SplatArgsWorker])
121
111
 
122
112
  expected_first_tick = time + 1800
123
113
 
data/test/test_sidetiq.rb CHANGED
@@ -4,13 +4,11 @@ class TestSidetiq < Sidetiq::TestCase
4
4
  def test_schedules
5
5
  schedules = Sidetiq.schedules
6
6
 
7
- assert_equal 2, schedules.length
7
+ assert_includes schedules, ScheduledWorker.schedule
8
+ assert_includes schedules, BackfillWorker.schedule
8
9
 
9
- assert_includes schedules.keys, ScheduledWorker
10
- assert_includes schedules.keys, BackfillWorker
11
-
12
- assert_kind_of Sidetiq::Schedule, schedules[ScheduledWorker]
13
- assert_kind_of Sidetiq::Schedule, schedules[BackfillWorker]
10
+ assert_kind_of Sidetiq::Schedule, ScheduledWorker.schedule
11
+ assert_kind_of Sidetiq::Schedule, BackfillWorker.schedule
14
12
  end
15
13
 
16
14
  def test_workers
@@ -18,7 +16,6 @@ class TestSidetiq < Sidetiq::TestCase
18
16
 
19
17
  assert_includes workers, ScheduledWorker
20
18
  assert_includes workers, BackfillWorker
21
- assert_equal 2, workers.length
22
19
  end
23
20
 
24
21
  def test_scheduled
@@ -0,0 +1,22 @@
1
+ require_relative 'helper'
2
+
3
+ class TestSubclassTracking < Sidetiq::TestCase
4
+ class Foo
5
+ extend Sidetiq::SubclassTracking
6
+ end
7
+
8
+ class Bar < Foo
9
+ end
10
+
11
+ class Baz < Bar
12
+ end
13
+
14
+ def test_subclasses_non_recursive
15
+ assert_equal [Bar], Foo.subclasses
16
+ end
17
+
18
+ def test_subclasses_recursive
19
+ assert_equal [Bar, Baz], Foo.subclasses(true)
20
+ end
21
+ end
22
+
data/test/test_web.rb CHANGED
@@ -14,6 +14,7 @@ class TestWeb < Sidetiq::TestCase
14
14
  def setup
15
15
  super
16
16
  ScheduledWorker.jobs.clear
17
+ Sidetiq.stubs(:workers).returns([ScheduledWorker])
17
18
  end
18
19
 
19
20
  def test_home_tab
@@ -27,7 +28,7 @@ class TestWeb < Sidetiq::TestCase
27
28
  get '/sidetiq'
28
29
  assert_equal 200, last_response.status
29
30
 
30
- clock.schedules.each do |worker, schedule|
31
+ Sidetiq.workers.each do |worker|
31
32
  assert_match /#{worker.name}/, last_response.body
32
33
  assert_match /#{worker.get_sidekiq_options['queue']}/, last_response.body
33
34
  end
@@ -46,7 +47,7 @@ class TestWeb < Sidetiq::TestCase
46
47
  def test_schedule_page
47
48
  get "/sidetiq/ScheduledWorker/schedule"
48
49
  assert_equal 200, last_response.status
49
- schedule = clock.schedules[ScheduledWorker]
50
+ schedule = ScheduledWorker.schedule
50
51
 
51
52
  schedule.recurrence_rules.each do |rule|
52
53
  assert_match /#{rule.to_s}/, last_response.body
data/test/test_worker.rb CHANGED
@@ -24,6 +24,6 @@ class TestWorker < Sidetiq::TestCase
24
24
  end
25
25
 
26
26
  def test_options
27
- assert Sidetiq.schedules[BackfillWorker].backfill?
27
+ assert BackfillWorker.schedule.backfill?
28
28
  end
29
29
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidetiq
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0.rc2
4
+ version: 0.4.0.rc3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Svensson
@@ -184,6 +184,7 @@ files:
184
184
  - lib/sidetiq/middleware/history.rb
185
185
  - lib/sidetiq/schedulable.rb
186
186
  - lib/sidetiq/schedule.rb
187
+ - lib/sidetiq/subclass_tracking.rb
187
188
  - lib/sidetiq/supervisor.rb
188
189
  - lib/sidetiq/version.rb
189
190
  - lib/sidetiq/views/_home_nav.erb
@@ -212,6 +213,7 @@ files:
212
213
  - test/test_lock_redis.rb
213
214
  - test/test_schedule.rb
214
215
  - test/test_sidetiq.rb
216
+ - test/test_subclass_tracking.rb
215
217
  - test/test_version.rb
216
218
  - test/test_watcher.rb
217
219
  - test/test_web.rb
@@ -256,6 +258,7 @@ test_files:
256
258
  - test/test_lock_redis.rb
257
259
  - test/test_schedule.rb
258
260
  - test/test_sidetiq.rb
261
+ - test/test_subclass_tracking.rb
259
262
  - test/test_version.rb
260
263
  - test/test_watcher.rb
261
264
  - test/test_web.rb