sidekiq_schedulable 0.0.1 → 0.0.2
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.
- checksums.yaml +4 -4
- data/lib/sidekiq/schedulable.rb +3 -2
- data/lib/sidekiq_schedulable.rb +1 -1
- data/lib/sidekiq_schedulable/middleware/client.rb +1 -1
- data/lib/sidekiq_schedulable/middleware/server.rb +11 -5
- data/lib/sidekiq_schedulable/schedule.rb +15 -0
- data/lib/sidekiq_schedulable/startup.rb +6 -8
- data/lib/sidekiq_schedulable/version.rb +1 -1
- data/spec/sidekiq_schedulable_spec.rb +60 -13
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1064f6cde72a8cf64dc6d6b8ca33772fd07e82b2
|
4
|
+
data.tar.gz: 353880a557b65213b9638853962aa5cca164f59a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9cef8200ad866b2e733ca179af8055ae3d3813c29c54c3d62431af7eccd6da041bdc1bc5a9069f0029dafd230c74b9eae98c21e2c3b67ff1a5ef78a78433a401
|
7
|
+
data.tar.gz: e7c691de4d29031ffa8c210fb6d05b4a61716c3832b32bbfbb9b1f1c0f76729270de2ab266e5619fcc2dd85632f673ff4e27e60ee1e756ff46d07ee2d81f4d51
|
data/lib/sidekiq/schedulable.rb
CHANGED
@@ -5,10 +5,11 @@ module Sidekiq
|
|
5
5
|
end
|
6
6
|
|
7
7
|
module ClassMethods
|
8
|
-
def sidekiq_schedule(schedule)
|
8
|
+
def sidekiq_schedule(schedule, options = {})
|
9
9
|
SidekiqSchedulable.schedules[self.to_s] = {
|
10
10
|
worker: self,
|
11
|
-
at: schedule
|
11
|
+
at: schedule,
|
12
|
+
options: options
|
12
13
|
}
|
13
14
|
end
|
14
15
|
end
|
data/lib/sidekiq_schedulable.rb
CHANGED
@@ -3,18 +3,24 @@ require 'sidekiq_schedulable/schedule'
|
|
3
3
|
module SidekiqSchedulable
|
4
4
|
module Middleware
|
5
5
|
class Server
|
6
|
+
def initialize(schedules = {})
|
7
|
+
@schedules = schedules
|
8
|
+
end
|
9
|
+
|
6
10
|
def call(worker, item, queue)
|
11
|
+
start_time = Time.now
|
7
12
|
yield
|
8
13
|
ensure
|
9
|
-
schedule_next_job(
|
14
|
+
schedule_next_job(item, start_time) if item['scheduled']
|
10
15
|
end
|
11
16
|
|
12
17
|
private
|
13
18
|
|
14
|
-
def schedule_next_job(
|
15
|
-
|
16
|
-
|
17
|
-
|
19
|
+
def schedule_next_job(item, start_time)
|
20
|
+
class_name = item['class']
|
21
|
+
if schedule = @schedules[class_name]
|
22
|
+
Schedule.enqueue(schedule, start_time)
|
23
|
+
end
|
18
24
|
end
|
19
25
|
end
|
20
26
|
end
|
@@ -2,8 +2,23 @@ require 'parse-cron'
|
|
2
2
|
|
3
3
|
module SidekiqSchedulable
|
4
4
|
module Schedule
|
5
|
+
def self.enqueue(schedule, last_run = nil)
|
6
|
+
worker = schedule[:worker]
|
7
|
+
time = next_time(schedule[:at])
|
8
|
+
if schedule[:options][:last_run]
|
9
|
+
last_time = last_run || last_time(schedule[:at])
|
10
|
+
worker.perform_at(time, last_time.to_f)
|
11
|
+
else
|
12
|
+
worker.perform_at(time)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
5
16
|
def self.next_time(schedule)
|
6
17
|
CronParser.new(schedule).next(Time.now)
|
7
18
|
end
|
19
|
+
|
20
|
+
def self.last_time(schedule)
|
21
|
+
CronParser.new(schedule).last(Time.now)
|
22
|
+
end
|
8
23
|
end
|
9
24
|
end
|
@@ -12,11 +12,9 @@ module SidekiqSchedulable
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def schedule!
|
15
|
-
schedules.each do |
|
16
|
-
unless already_scheduled?(
|
17
|
-
|
18
|
-
worker = schedule[:worker]
|
19
|
-
worker.perform_at(time)
|
15
|
+
schedules.each do |klass_name, schedule|
|
16
|
+
unless already_scheduled?(klass_name)
|
17
|
+
Schedule.enqueue(schedule)
|
20
18
|
end
|
21
19
|
end
|
22
20
|
end
|
@@ -25,15 +23,15 @@ module SidekiqSchedulable
|
|
25
23
|
|
26
24
|
attr_reader :schedules, :current_jobs
|
27
25
|
|
28
|
-
def already_scheduled?(
|
26
|
+
def already_scheduled?(klass_name)
|
29
27
|
scheduled_jobs.any? do |job|
|
30
|
-
job.item['class'] ==
|
28
|
+
job.item['class'] == klass_name
|
31
29
|
end
|
32
30
|
end
|
33
31
|
|
34
32
|
def scheduled_jobs
|
35
33
|
@scheduled_jobs ||= current_jobs.select do |job|
|
36
|
-
job.item['
|
34
|
+
job.item['scheduled']
|
37
35
|
end
|
38
36
|
end
|
39
37
|
end
|
@@ -12,34 +12,65 @@ describe SidekiqSchedulable do
|
|
12
12
|
include Sidekiq::Schedulable
|
13
13
|
|
14
14
|
sidekiq_schedule '*/10 * * * * *'
|
15
|
+
|
16
|
+
def perform
|
17
|
+
:done
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class AnotherWorker
|
22
|
+
include Sidekiq::Worker
|
23
|
+
include Sidekiq::Schedulable
|
24
|
+
|
25
|
+
sidekiq_schedule '0 12 * * * *', last_run: true
|
26
|
+
|
27
|
+
def perform(last_run)
|
28
|
+
Time.now - Time.at(last_run)
|
29
|
+
end
|
15
30
|
end
|
16
31
|
|
17
32
|
let(:midnight) { Time.new(2015, 10, 1, 0, 0, 0) }
|
18
33
|
let(:next_ten_minutes) { midnight + 10 * 60 }
|
19
34
|
|
35
|
+
let(:schedules) {
|
36
|
+
{
|
37
|
+
'TestWorker' => {
|
38
|
+
worker: TestWorker,
|
39
|
+
at: '*/10 * * * * *',
|
40
|
+
options: {}
|
41
|
+
},
|
42
|
+
'AnotherWorker' => {
|
43
|
+
worker: AnotherWorker,
|
44
|
+
at: '0 12 * * * *',
|
45
|
+
options: { last_run: true }
|
46
|
+
}
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
20
50
|
before do
|
21
51
|
Timecop.freeze(midnight)
|
22
52
|
end
|
23
53
|
|
24
54
|
after do
|
25
|
-
|
55
|
+
Sidekiq::Worker.clear_all
|
26
56
|
end
|
27
57
|
|
28
58
|
it "adds the schedule to the schedules" do
|
29
|
-
schedule = SidekiqSchedulable.schedules[
|
59
|
+
schedule = SidekiqSchedulable.schedules['TestWorker']
|
30
60
|
|
31
61
|
expect(schedule[:at]).to eq('*/10 * * * * *')
|
32
62
|
expect(schedule[:worker]).to eq(TestWorker)
|
63
|
+
expect(schedule[:options]).to eq({})
|
33
64
|
end
|
34
65
|
|
35
66
|
describe SidekiqSchedulable::Middleware::Server do
|
36
67
|
let(:worker) { TestWorker.new }
|
37
|
-
let(:middleware) { SidekiqSchedulable::Middleware::Server.new }
|
68
|
+
let(:middleware) { SidekiqSchedulable::Middleware::Server.new(schedules) }
|
38
69
|
|
39
70
|
it "ensures the job is re-enqueued for next time" do
|
40
71
|
expect {
|
41
|
-
middleware.call(worker, { '
|
42
|
-
raise
|
72
|
+
middleware.call(worker, { 'scheduled' => true, 'class' => 'TestWorker' }, 'a_queue') do
|
73
|
+
raise 'Error'
|
43
74
|
end
|
44
75
|
}.to raise_error RuntimeError, "Error"
|
45
76
|
|
@@ -50,17 +81,23 @@ describe SidekiqSchedulable do
|
|
50
81
|
end
|
51
82
|
|
52
83
|
it "does not re-schedule if the job has no schedule" do
|
53
|
-
middleware.call(worker, {}, '
|
84
|
+
middleware.call(worker, {}, 'a_queue') do
|
54
85
|
true
|
55
86
|
end
|
56
87
|
|
57
88
|
expect(TestWorker.jobs.size).to eq(0)
|
58
89
|
end
|
59
|
-
end
|
60
90
|
|
61
|
-
|
62
|
-
|
63
|
-
|
91
|
+
it "adds the last_run argument based on the last job start time" do
|
92
|
+
middleware.call(worker, { 'scheduled' => true, 'class' => 'AnotherWorker' }, 'a_queue') do
|
93
|
+
true
|
94
|
+
end
|
95
|
+
|
96
|
+
expect(AnotherWorker.jobs.size).to eq(1)
|
97
|
+
expect(AnotherWorker.jobs.first['args']).to eq([Time.now.to_f])
|
98
|
+
expect { AnotherWorker.drain }.to_not raise_error
|
99
|
+
end
|
100
|
+
end
|
64
101
|
|
65
102
|
describe SidekiqSchedulable::Middleware::Client do
|
66
103
|
let(:middleware) { SidekiqSchedulable::Middleware::Client.new(schedules) }
|
@@ -68,17 +105,17 @@ describe SidekiqSchedulable do
|
|
68
105
|
it "adds the schedule to the job item" do
|
69
106
|
item = {}
|
70
107
|
|
71
|
-
middleware.call(
|
108
|
+
middleware.call('TestWorker', item, 'a queue', nil) do
|
72
109
|
true
|
73
110
|
end
|
74
111
|
|
75
|
-
expect(item['
|
112
|
+
expect(item['scheduled']).to eq(true)
|
76
113
|
end
|
77
114
|
|
78
115
|
it "does not add the schedule if the worker has no schedule" do
|
79
116
|
item = {}
|
80
117
|
|
81
|
-
middleware.call(
|
118
|
+
middleware.call('Array', item, 'a_queue', nil) do
|
82
119
|
true
|
83
120
|
end
|
84
121
|
|
@@ -100,6 +137,16 @@ describe SidekiqSchedulable do
|
|
100
137
|
expect(TestWorker.jobs.first['at']).to eq(next_ten_minutes.to_f)
|
101
138
|
end
|
102
139
|
|
140
|
+
it "adds the last_run argument based on the schedule" do
|
141
|
+
last_run = midnight - 60 * 60 * 12
|
142
|
+
|
143
|
+
SidekiqSchedulable::Startup.schedule!(schedules, current_jobs)
|
144
|
+
|
145
|
+
expect(AnotherWorker.jobs.size).to eq(1)
|
146
|
+
expect(AnotherWorker.jobs.first['args']).to eq([last_run.to_f])
|
147
|
+
expect { AnotherWorker.drain }.to_not raise_error
|
148
|
+
end
|
149
|
+
|
103
150
|
it "does not enqueue a duplicate job for the given worker" do
|
104
151
|
SidekiqSchedulable::Startup.schedule!(schedules, current_jobs)
|
105
152
|
SidekiqSchedulable::Startup.schedule!(schedules, current_jobs)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sidekiq_schedulable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin Buchanan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-10-
|
11
|
+
date: 2015-10-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sidekiq
|