rekiq 0.0.1 → 0.5.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.
- checksums.yaml +4 -4
- data/README.md +31 -29
- data/lib/rekiq/configuration.rb +19 -6
- data/lib/rekiq/exceptions.rb +1 -0
- data/lib/rekiq/job.rb +49 -42
- data/lib/rekiq/middleware/work_overseer.rb +7 -17
- data/lib/rekiq/scheduler.rb +1 -1
- data/lib/rekiq/validator.rb +68 -0
- data/lib/rekiq/version.rb +1 -1
- data/lib/rekiq/worker.rb +8 -14
- data/rekiq.gemspec +3 -3
- data/spec/factories/configuration.rb +8 -0
- data/spec/factories/job.rb +4 -4
- data/spec/rekiq/configuration_spec.rb +121 -0
- data/spec/rekiq/job_spec.rb +32 -33
- data/spec/rekiq/middleware/work_overseer_spec.rb +2 -2
- data/spec/rekiq/worker_spec.rb +3 -3
- metadata +9 -19
- data/lib/rekiq/schedule_format_validator.rb +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 512f24c5f3a752e5df2fec6362c7f4b527303eee
|
4
|
+
data.tar.gz: 8cd79188800b644ecfa72b9d9a1a7e37b4e39f57
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a864ed822e261ac6cbcdfdc32bcfd8a187d9845d922911e882e57e876249120c403a383c880b464355b4f04624042a8ffbf8cb31f53ecd2bb6f0b10803ed21ef
|
7
|
+
data.tar.gz: 22d22ab155bd60846184e9b60d9dba60f483ffd3529e391cb609a5e83724b5a75c5b607079b35eeee215713788a95538ba4511732fc54a3767d016453676dd9d
|
data/README.md
CHANGED
@@ -15,59 +15,61 @@ worker, or even to schedule a time for the worker to start. Now wouldn't it be
|
|
15
15
|
nice if it also allowed us to schedule a worker to do work recurringly? That's
|
16
16
|
what rekiq purposes to do.
|
17
17
|
|
18
|
-
|
19
|
-
work friday at 23:00
|
18
|
+
For example, rekiq allows you to schedule a worker to repeat the same
|
19
|
+
work every friday at 23:00.
|
20
20
|
|
21
|
-
##
|
21
|
+
## Dependencies
|
22
22
|
|
23
23
|
Tested with:
|
24
24
|
|
25
|
-
*
|
26
|
-
*
|
27
|
-
* ice_cube 0.12.1
|
25
|
+
* ruby 2.1.1, 2.0.0 and 1.9.3
|
26
|
+
* sidekiq 3.2.1
|
28
27
|
|
29
28
|
## Installation
|
30
29
|
|
31
30
|
Add this line to your application's Gemfile:
|
32
31
|
|
33
|
-
gem 'rekiq'
|
32
|
+
gem 'rekiq'
|
34
33
|
|
35
34
|
And then execute:
|
36
35
|
|
37
36
|
$ bundle
|
38
37
|
|
39
|
-
Or
|
38
|
+
Or install it yourself as:
|
40
39
|
|
41
|
-
|
40
|
+
$ gem install rekiq
|
42
41
|
|
43
|
-
|
42
|
+
## Basic usage
|
44
43
|
|
45
|
-
|
46
|
-
require 'rekiq'
|
44
|
+
1. Require rekiq after sidekiq:
|
47
45
|
|
48
|
-
|
46
|
+
require 'sidekiq'
|
47
|
+
require 'rekiq'
|
48
|
+
|
49
|
+
2. We need a 'schedule' object (responsible for returning the time at which the
|
49
50
|
worker should start) which must respond to method next_occurrence and
|
50
|
-
receives one argument of type Time more at [schedule]().
|
51
|
-
[ice_cube](https://github.com/seejohnrun/ice_cube)
|
51
|
+
receives one argument of type Time (more at [The schedule object](https://github.com/junhanamaki/rekiq/wiki/The-schedule-object)).
|
52
|
+
For our example we'll be using the gem [ice_cube](https://github.com/seejohnrun/ice_cube)
|
53
|
+
(don't forget to require it):
|
52
54
|
|
53
|
-
|
54
|
-
|
55
|
-
|
55
|
+
# define worker as normal
|
56
|
+
class ExampleWorker
|
57
|
+
include Sidekiq::Worker
|
56
58
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
59
|
+
def perform(arg1, arg2)
|
60
|
+
# Do some work
|
61
|
+
end
|
62
|
+
end
|
61
63
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
64
|
+
# create schedule for worker to repeat every friday at 2am
|
65
|
+
schedule = IceCube::Schedule.new do |s|
|
66
|
+
s.rrule IceCube::Rule.daily.day(:friday).hour_of_day(2)
|
67
|
+
end
|
66
68
|
|
67
|
-
|
68
|
-
|
69
|
+
# now just start your worker
|
70
|
+
ExampleWorker.perform_recurringly(schedule, 'argument_1', 'argument_2')
|
69
71
|
|
70
|
-
You can use your own schedule object, configure worker to reschedule before or
|
72
|
+
You can use your own schedule object, configure worker to reschedule before or
|
71
73
|
after work is done, set margin, and much more! So please check
|
72
74
|
[wiki](https://github.com/junhanamaki/rekiq/wiki) for more details.
|
73
75
|
|
data/lib/rekiq/configuration.rb
CHANGED
@@ -1,25 +1,38 @@
|
|
1
|
+
require 'rekiq/validator'
|
2
|
+
|
1
3
|
module Rekiq
|
2
4
|
class Configuration
|
3
|
-
|
5
|
+
include Validator
|
6
|
+
|
7
|
+
attr_accessor :shift, :schedule_post_work, :schedule_expired,
|
4
8
|
:expiration_margin
|
5
9
|
|
10
|
+
validate :shift, :numeric
|
11
|
+
validate :schedule_post_work, :bool
|
12
|
+
validate :expiration_margin, :numeric, greater_than_or_equal_to: 0
|
13
|
+
validate :schedule_expired, :bool
|
14
|
+
|
6
15
|
def initialize
|
7
|
-
#
|
8
|
-
self.
|
16
|
+
# the value of the shift to apply relative to time returned by schedule
|
17
|
+
self.shift = 0
|
9
18
|
|
10
|
-
# if
|
11
|
-
|
12
|
-
self.schedule_expired = false
|
19
|
+
# if next work is scheduled after or before the worker completes
|
20
|
+
self.schedule_post_work = false
|
13
21
|
|
14
22
|
# indicates the margin after which a work is considered expired
|
15
23
|
# default to 0
|
16
24
|
self.expiration_margin = 0
|
25
|
+
|
26
|
+
# if expired works are to be scheduled
|
27
|
+
# an expired work is a work that has a time bellow current_time - margin
|
28
|
+
self.schedule_expired = false
|
17
29
|
end
|
18
30
|
end
|
19
31
|
|
20
32
|
class << self
|
21
33
|
def configure
|
22
34
|
yield configuration
|
35
|
+
configuration.validate!
|
23
36
|
end
|
24
37
|
|
25
38
|
def configuration
|
data/lib/rekiq/exceptions.rb
CHANGED
data/lib/rekiq/job.rb
CHANGED
@@ -1,66 +1,65 @@
|
|
1
1
|
require 'yaml'
|
2
|
-
require 'rekiq/schedule_format_validator'
|
3
2
|
|
4
3
|
module Rekiq
|
5
4
|
class Job
|
6
|
-
include
|
7
|
-
include ActiveModel::Validations::Callbacks
|
5
|
+
include Validator
|
8
6
|
|
9
|
-
attr_accessor :schedule, :shift, :
|
7
|
+
attr_accessor :schedule, :shift, :schedule_post_work, :schedule_expired,
|
10
8
|
:expiration_margin
|
11
9
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
10
|
+
validate :schedule, :schedule
|
11
|
+
validate :shift, :numeric, allow_nil: true
|
12
|
+
validate :schedule_post_work, :bool, allow_nil: true
|
13
|
+
validate :schedule_expired, :numeric, allow_nil: true
|
14
|
+
validate :expiration_margin, :bool, allow_nil: true
|
15
|
+
|
16
|
+
def self.from_array(array)
|
17
|
+
attributes = {}.tap do |hash|
|
18
|
+
hash['schedule'] = YAML::load(array[0])
|
19
|
+
hash['shift'] = array[1]
|
20
|
+
hash['schedule_post_work'] = array[2]
|
21
|
+
hash['schedule_expired'] = array[3]
|
22
|
+
hash['expiration_margin'] = array[4]
|
23
|
+
end
|
24
|
+
|
25
|
+
new(attributes)
|
27
26
|
end
|
28
27
|
|
29
28
|
def initialize(attributes = {})
|
30
|
-
self.schedule
|
31
|
-
self.shift
|
32
|
-
self.
|
33
|
-
self.schedule_expired
|
34
|
-
self.expiration_margin
|
29
|
+
self.schedule = attributes['schedule']
|
30
|
+
self.shift = attributes['shift']
|
31
|
+
self.schedule_post_work = attributes['schedule_post_work']
|
32
|
+
self.schedule_expired = attributes['schedule_expired']
|
33
|
+
self.expiration_margin = attributes['expiration_margin']
|
35
34
|
end
|
36
35
|
|
37
|
-
def
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
36
|
+
def to_array
|
37
|
+
[
|
38
|
+
YAML::dump(schedule),
|
39
|
+
shift,
|
40
|
+
schedule_post_work,
|
41
|
+
schedule_expired,
|
42
|
+
expiration_margin
|
43
|
+
]
|
45
44
|
end
|
46
45
|
|
47
46
|
def next_work_time(from = Time.now)
|
48
|
-
|
47
|
+
from_with_shift = shift_val > 0 ? from - shift_val : from
|
49
48
|
|
50
|
-
search_next_work_time(
|
49
|
+
search_next_work_time(from_with_shift)
|
51
50
|
end
|
52
51
|
|
53
52
|
def next_work_time_from_work_time(from)
|
54
|
-
|
53
|
+
from_with_shift = from - shift_val
|
55
54
|
|
56
|
-
search_next_work_time(
|
55
|
+
search_next_work_time(from_with_shift)
|
57
56
|
end
|
58
57
|
|
59
|
-
def
|
60
|
-
unless
|
61
|
-
|
58
|
+
def schedule_post_work?
|
59
|
+
unless schedule_post_work.nil?
|
60
|
+
schedule_post_work
|
62
61
|
else
|
63
|
-
Rekiq.configuration.
|
62
|
+
Rekiq.configuration.schedule_post_work
|
64
63
|
end
|
65
64
|
end
|
66
65
|
|
@@ -69,11 +68,11 @@ module Rekiq
|
|
69
68
|
def search_next_work_time(from)
|
70
69
|
if schedule_expired?
|
71
70
|
from = schedule.next_occurrence(from)
|
72
|
-
work_time = from.nil? ? nil : from +
|
71
|
+
work_time = from.nil? ? nil : from + shift_val
|
73
72
|
else
|
74
73
|
begin
|
75
74
|
from = schedule.next_occurrence(from)
|
76
|
-
work_time = from.nil? ? nil : from +
|
75
|
+
work_time = from.nil? ? nil : from + shift_val
|
77
76
|
end until work_time.nil? || work_time > expiration_time
|
78
77
|
end
|
79
78
|
|
@@ -96,6 +95,14 @@ module Rekiq
|
|
96
95
|
end
|
97
96
|
end
|
98
97
|
|
98
|
+
def shift_val
|
99
|
+
unless shift.nil?
|
100
|
+
shift
|
101
|
+
else
|
102
|
+
Rekiq.configuration.shift
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
99
106
|
def expiration_time
|
100
107
|
Time.now - expiration_margin_val
|
101
108
|
end
|
@@ -13,30 +13,20 @@ module Rekiq
|
|
13
13
|
:scheduled_work_time
|
14
14
|
|
15
15
|
def call(worker, msg, queue)
|
16
|
-
return yield unless msg['rq:job']
|
16
|
+
return yield unless msg['rq:job'] and msg['retry_count'].nil?
|
17
17
|
|
18
18
|
self.worker_name = worker.class.name
|
19
19
|
self.queue = queue
|
20
20
|
self.args = msg['args']
|
21
|
-
self.job = Job.
|
21
|
+
self.job = Job.from_array(msg['rq:job'])
|
22
22
|
self.addon = msg['rq:addon']
|
23
|
+
self.scheduled_work_time = Time.at(msg['rq:at'].to_f)
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
reschedule_post_work = job.reschedule_post_work?
|
27
|
-
|
28
|
-
if reschedule_post_work
|
29
|
-
begin
|
30
|
-
yield
|
31
|
-
ensure
|
32
|
-
reschedule
|
33
|
-
end
|
34
|
-
else
|
35
|
-
reschedule
|
36
|
-
yield
|
37
|
-
end
|
38
|
-
else
|
25
|
+
begin
|
26
|
+
reschedule unless job.schedule_post_work?
|
39
27
|
yield
|
28
|
+
ensure
|
29
|
+
reschedule if job.schedule_post_work?
|
40
30
|
end
|
41
31
|
end
|
42
32
|
|
data/lib/rekiq/scheduler.rb
CHANGED
@@ -0,0 +1,68 @@
|
|
1
|
+
module Rekiq
|
2
|
+
module Validator
|
3
|
+
module ClassMethods
|
4
|
+
attr_accessor :for_validation
|
5
|
+
|
6
|
+
def validate(attribute_name, type, options = {})
|
7
|
+
options[:allow_nil] = true if options[:allow_nil].nil?
|
8
|
+
|
9
|
+
self.for_validation << {
|
10
|
+
attribute_name: attribute_name,
|
11
|
+
type: type,
|
12
|
+
options: options
|
13
|
+
}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.included(base)
|
18
|
+
base.extend(ClassMethods)
|
19
|
+
base.for_validation = []
|
20
|
+
end
|
21
|
+
|
22
|
+
NUMERIC_OPTIONS = {
|
23
|
+
greater_than_or_equal_to: :>=
|
24
|
+
}
|
25
|
+
|
26
|
+
def validate!
|
27
|
+
self.class.for_validation.each do |v|
|
28
|
+
attribute_name = v[:attribute_name]
|
29
|
+
type = v[:type]
|
30
|
+
options = v[:options]
|
31
|
+
value = send(attribute_name)
|
32
|
+
|
33
|
+
unless options[:allow_nil] and send(attribute_name).nil?
|
34
|
+
send("validate_#{type}!", attribute_name, value, options)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def validate_numeric!(attribute_name, value, options)
|
40
|
+
unless value.is_a?(Numeric)
|
41
|
+
raise InvalidAttributeValue, "#{attribute_name} must be numeric"
|
42
|
+
end
|
43
|
+
|
44
|
+
options.each do |key, option_value|
|
45
|
+
if NUMERIC_OPTIONS.key?(key) and
|
46
|
+
!value.send(NUMERIC_OPTIONS[key], option_value)
|
47
|
+
raise InvalidAttributeValue, "#{attribute_name} must be greater " \
|
48
|
+
'or equal to 0'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def validate_bool!(attribute_name, value, options)
|
54
|
+
unless [true, false].include?(value)
|
55
|
+
raise InvalidAttributeValue, "#{attribute_name} must be either true " \
|
56
|
+
'or false'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def validate_schedule!(attribute_name, value, options)
|
61
|
+
unless value.respond_to?(:next_occurrence) and
|
62
|
+
value.method(:next_occurrence).arity.abs == 1
|
63
|
+
raise InvalidConf, '#attribute_name must respond to next_occurrence ' \
|
64
|
+
'and receive one argument of type Time'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/lib/rekiq/version.rb
CHANGED
data/lib/rekiq/worker.rb
CHANGED
@@ -5,12 +5,8 @@ require 'rekiq/scheduler'
|
|
5
5
|
module Rekiq
|
6
6
|
module Worker
|
7
7
|
class Configuration
|
8
|
-
attr_accessor :shift, :
|
8
|
+
attr_accessor :shift, :schedule_post_work, :schedule_expired,
|
9
9
|
:expiration_margin, :addon
|
10
|
-
|
11
|
-
def append_to_msg(addon)
|
12
|
-
self.addon = addon
|
13
|
-
end
|
14
10
|
end
|
15
11
|
|
16
12
|
module ClassMethods
|
@@ -20,11 +16,13 @@ module Rekiq
|
|
20
16
|
|
21
17
|
job =
|
22
18
|
Rekiq::Job
|
23
|
-
.new 'schedule'
|
24
|
-
'shift'
|
25
|
-
'
|
26
|
-
'schedule_expired'
|
27
|
-
'expiration_margin'
|
19
|
+
.new 'schedule' => schedule,
|
20
|
+
'shift' => config.shift,
|
21
|
+
'schedule_post_work' => config.schedule_post_work,
|
22
|
+
'schedule_expired' => config.schedule_expired,
|
23
|
+
'expiration_margin' => config.expiration_margin
|
24
|
+
|
25
|
+
job.validate!
|
28
26
|
|
29
27
|
queue = get_sidekiq_options['queue']
|
30
28
|
|
@@ -39,10 +37,6 @@ module Rekiq
|
|
39
37
|
"#{work_time} with jid #{jid}"
|
40
38
|
|
41
39
|
jid
|
42
|
-
rescue StandardError => e
|
43
|
-
raise Rekiq::StandardError,
|
44
|
-
'unable to schedule worker',
|
45
|
-
e.backtrace
|
46
40
|
end
|
47
41
|
end
|
48
42
|
end
|
data/rekiq.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.email = ["jun.hanamaki@gmail.com"]
|
11
11
|
spec.summary = %q{recurring worker extension for sidekiq}
|
12
12
|
spec.description = %q{}
|
13
|
-
spec.homepage = ""
|
13
|
+
spec.homepage = "https://github.com/junhanamaki/rekiq"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0")
|
@@ -18,6 +18,8 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
+
spec.required_ruby_version = '>= 1.9.3'
|
22
|
+
|
21
23
|
spec.add_development_dependency 'bundler', '~> 1.6'
|
22
24
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
23
25
|
spec.add_development_dependency 'simplecov', '~> 0.9'
|
@@ -26,6 +28,4 @@ Gem::Specification.new do |spec|
|
|
26
28
|
spec.add_development_dependency 'jazz_hands', '~> 0.5'
|
27
29
|
spec.add_development_dependency 'ice_cube', '~> 0.12'
|
28
30
|
spec.add_development_dependency 'sidekiq', '~> 3.2'
|
29
|
-
|
30
|
-
spec.add_runtime_dependency 'activemodel', '~> 4.1'
|
31
31
|
end
|
data/spec/factories/job.rb
CHANGED
@@ -6,10 +6,10 @@ FactoryGirl.define do
|
|
6
6
|
schedule { IceCube::Schedule.new(Time.now + 3600) }
|
7
7
|
|
8
8
|
trait :randomized_attributes do
|
9
|
-
shift
|
10
|
-
|
11
|
-
schedule_expired
|
12
|
-
expiration_margin
|
9
|
+
shift { [*0..100].sample }
|
10
|
+
schedule_post_work { [nil, false, true].sample }
|
11
|
+
schedule_expired { [nil, false, true].sample }
|
12
|
+
expiration_margin { [*0..100].sample }
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rekiq::Configuration do
|
4
|
+
describe '.new' do
|
5
|
+
context 'for created Configuration instance' do
|
6
|
+
before { @configuration = Rekiq::Configuration.new }
|
7
|
+
|
8
|
+
it 'sets shift as 0 by default' do
|
9
|
+
expect(@configuration.shift).to eq(0)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'sets schedule_post_work as false by default' do
|
13
|
+
expect(@configuration.schedule_post_work).to eq(false)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'sets expiration_margin as 0 by default' do
|
17
|
+
expect(@configuration.expiration_margin).to eq(0)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'sets schedule_expired as false by default' do
|
21
|
+
expect(@configuration.schedule_expired).to eq(false)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#validate!' do
|
27
|
+
context 'for instance with non numeric shift' do
|
28
|
+
before { @configuration = build(:configuration, shift: [1]) }
|
29
|
+
|
30
|
+
it 'raises error' do
|
31
|
+
expect do
|
32
|
+
@configuration.validate!
|
33
|
+
end.to raise_error
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'for instance with numeric shift' do
|
38
|
+
before { @configuration = build(:configuration) }
|
39
|
+
|
40
|
+
it 'does not raise error' do
|
41
|
+
expect do
|
42
|
+
@configuration.validate!
|
43
|
+
end.not_to raise_error
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'for instance with non bool schedule_post_work' do
|
48
|
+
before do
|
49
|
+
@configuration = build(:configuration, schedule_post_work: 'true')
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'raises error' do
|
53
|
+
expect do
|
54
|
+
@configuration.validate!
|
55
|
+
end.to raise_error
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'for instance with bool schedule_post_work' do
|
60
|
+
before { @configuration = build(:configuration) }
|
61
|
+
|
62
|
+
it 'does not raise error' do
|
63
|
+
expect do
|
64
|
+
@configuration.validate!
|
65
|
+
end.not_to raise_error
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'for instance with non numeric expiration_margin' do
|
70
|
+
before { @configuration = build(:configuration, expiration_margin: '1') }
|
71
|
+
|
72
|
+
it 'raises error' do
|
73
|
+
expect do
|
74
|
+
@configuration.validate!
|
75
|
+
end.to raise_error
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'for instance with negative expiration_margin' do
|
80
|
+
before { @configuration = build(:configuration, expiration_margin: -1) }
|
81
|
+
|
82
|
+
it 'raises error' do
|
83
|
+
expect do
|
84
|
+
@configuration.validate!
|
85
|
+
end.to raise_error
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context 'for instance with 0 or positive expiration_margin' do
|
90
|
+
before { @configuration = build(:configuration) }
|
91
|
+
|
92
|
+
it 'does not raise error' do
|
93
|
+
expect do
|
94
|
+
@configuration.validate!
|
95
|
+
end.not_to raise_error
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'for instance with non bool schedule_expired' do
|
100
|
+
before do
|
101
|
+
@configuration = build(:configuration, schedule_expired: 'false')
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'raises error' do
|
105
|
+
expect do
|
106
|
+
@configuration.validate!
|
107
|
+
end.to raise_error
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'for instance with bool schedule_expired' do
|
112
|
+
before { @configuration = build(:configuration) }
|
113
|
+
|
114
|
+
it 'does not raise error' do
|
115
|
+
expect do
|
116
|
+
@configuration.validate!
|
117
|
+
end.not_to raise_error
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
data/spec/rekiq/job_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Rekiq::Job do
|
4
|
-
describe '
|
4
|
+
describe '.new' do
|
5
5
|
context 'when no args' do
|
6
6
|
before { @job = Rekiq::Job.new }
|
7
7
|
|
@@ -9,12 +9,12 @@ describe Rekiq::Job do
|
|
9
9
|
expect(@job).not_to be_nil
|
10
10
|
end
|
11
11
|
|
12
|
-
it 'sets attribute shift as
|
13
|
-
expect(@job.shift).to eq(
|
12
|
+
it 'sets attribute shift as nil' do
|
13
|
+
expect(@job.shift).to eq(nil)
|
14
14
|
end
|
15
15
|
|
16
|
-
it 'sets
|
17
|
-
expect(@job.
|
16
|
+
it 'sets schedule_post_work as nil' do
|
17
|
+
expect(@job.schedule_post_work).to eq(nil)
|
18
18
|
end
|
19
19
|
|
20
20
|
it 'sets schedule_expired as nil' do
|
@@ -33,19 +33,19 @@ describe Rekiq::Job do
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
-
context 'when
|
36
|
+
context 'when schedule_post_work and ' \
|
37
37
|
'schedule_expired passed as true' do
|
38
|
-
let(:
|
38
|
+
let(:schedule_post_work) { true }
|
39
39
|
let(:schedule_expired) { true }
|
40
40
|
before do
|
41
41
|
@job =
|
42
42
|
Rekiq::Job.new \
|
43
|
-
'
|
43
|
+
'schedule_post_work' => schedule_post_work,
|
44
44
|
'schedule_expired' => schedule_expired
|
45
45
|
end
|
46
46
|
|
47
|
-
it 'sets
|
48
|
-
expect(@job.
|
47
|
+
it 'sets schedule_post_work to true' do
|
48
|
+
expect(@job.schedule_post_work).to eq(true)
|
49
49
|
end
|
50
50
|
|
51
51
|
it 'sets schedule_expired to true' do
|
@@ -54,11 +54,11 @@ describe Rekiq::Job do
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
-
describe '
|
58
|
-
context '
|
57
|
+
describe '.from_array' do
|
58
|
+
context 'array returned from Job#to_array' do
|
59
59
|
let(:job) { build(:job, :randomized_attributes) }
|
60
|
-
let(:
|
61
|
-
before { @job = Rekiq::Job.
|
60
|
+
let(:array) { job.to_array }
|
61
|
+
before { @job = Rekiq::Job.from_array(array) }
|
62
62
|
|
63
63
|
it 'returns job instance' do
|
64
64
|
expect(@job.class).to eq(Rekiq::Job)
|
@@ -68,8 +68,8 @@ describe Rekiq::Job do
|
|
68
68
|
expect(@job.shift).to eq(job.shift)
|
69
69
|
end
|
70
70
|
|
71
|
-
it 'returns job with
|
72
|
-
expect(@job.
|
71
|
+
it 'returns job with schedule_post_work value before serialization' do
|
72
|
+
expect(@job.schedule_post_work).to eq(job.schedule_post_work)
|
73
73
|
end
|
74
74
|
|
75
75
|
it 'returns job with schedule_expired value before serialization' do
|
@@ -86,40 +86,39 @@ describe Rekiq::Job do
|
|
86
86
|
|
87
87
|
it 'returns job with working schedule' do
|
88
88
|
time = Time.now
|
89
|
-
expect(@job.schedule.next_occurrence(time))
|
90
|
-
eq(job.schedule.next_occurrence(time))
|
91
|
-
)
|
89
|
+
expect(@job.schedule.next_occurrence(time))
|
90
|
+
.to eq(job.schedule.next_occurrence(time))
|
92
91
|
end
|
93
92
|
end
|
94
93
|
end
|
95
94
|
|
96
|
-
describe '
|
95
|
+
describe '#to_array' do
|
97
96
|
context 'given job instance' do
|
98
97
|
let(:job) { build(:job, :randomized_attributes) }
|
99
|
-
before { @val = job.
|
98
|
+
before { @val = job.to_array }
|
100
99
|
|
101
|
-
it 'returns an
|
102
|
-
expect(@val.class).to eq(
|
100
|
+
it 'returns an array' do
|
101
|
+
expect(@val.class).to eq(Array)
|
103
102
|
end
|
104
103
|
|
105
|
-
it 'returns
|
106
|
-
expect(@val[
|
104
|
+
it 'returns array with YAML::dump(schedule) value at index 0' do
|
105
|
+
expect(@val[0]).to eq(YAML::dump(job.schedule))
|
107
106
|
end
|
108
107
|
|
109
|
-
it 'returns
|
110
|
-
expect(@val[
|
108
|
+
it 'returns array with shift value at index 1' do
|
109
|
+
expect(@val[1]).to eq(job.shift)
|
111
110
|
end
|
112
111
|
|
113
|
-
it 'returns
|
114
|
-
expect(@val[
|
112
|
+
it 'returns array with schedule_post_work value at index 2' do
|
113
|
+
expect(@val[2]).to eq(job.schedule_post_work)
|
115
114
|
end
|
116
115
|
|
117
|
-
it 'returns
|
118
|
-
expect(@val[
|
116
|
+
it 'returns array with schedule_expired value at index 3' do
|
117
|
+
expect(@val[3]).to eq(job.schedule_expired)
|
119
118
|
end
|
120
119
|
|
121
|
-
it 'returns
|
122
|
-
expect(@val[
|
120
|
+
it 'returns array with expiration_margin value at index 4' do
|
121
|
+
expect(@val[4]).to eq(job.expiration_margin)
|
123
122
|
end
|
124
123
|
end
|
125
124
|
end
|
@@ -15,7 +15,7 @@ describe Rekiq::Middleware::WorkOverseer do
|
|
15
15
|
|
16
16
|
context 'msg with rq:job key (existing job)' do
|
17
17
|
let(:job) { build(:job, schedule: schedule) }
|
18
|
-
let(:msg) { { 'rq:job' => job.
|
18
|
+
let(:msg) { { 'rq:job' => job.to_array, 'args' => args } }
|
19
19
|
|
20
20
|
it 'yields once' do
|
21
21
|
expect do |b|
|
@@ -45,7 +45,7 @@ describe Rekiq::Middleware::WorkOverseer do
|
|
45
45
|
|
46
46
|
context 'msg with job retry info and rq:job (existing job)' do
|
47
47
|
let(:job) { build(:job, schedule: schedule) }
|
48
|
-
let(:msg) { { 'rq:job' => job.
|
48
|
+
let(:msg) { { 'rq:job' => job.to_array, 'retry_count' => 0,
|
49
49
|
'args' => args } }
|
50
50
|
|
51
51
|
it 'yields once' do
|
data/spec/rekiq/worker_spec.rb
CHANGED
@@ -58,10 +58,10 @@ describe Rekiq::Worker do
|
|
58
58
|
end.to yield_control.once
|
59
59
|
end
|
60
60
|
|
61
|
-
it 'sets shift in job' do
|
62
|
-
|
61
|
+
it 'sets shift in rq:job' do
|
62
|
+
array = ExampleWorker.jobs[0]['rq:job']
|
63
63
|
|
64
|
-
expect(
|
64
|
+
expect(array[1]).to eq(shift)
|
65
65
|
end
|
66
66
|
|
67
67
|
it 'schedules worker for one hour minus 5 minutes from now' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rekiq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- junhanamaki
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-07-
|
11
|
+
date: 2014-07-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -122,20 +122,6 @@ dependencies:
|
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '3.2'
|
125
|
-
- !ruby/object:Gem::Dependency
|
126
|
-
name: activemodel
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
128
|
-
requirements:
|
129
|
-
- - "~>"
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
version: '4.1'
|
132
|
-
type: :runtime
|
133
|
-
prerelease: false
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
135
|
-
requirements:
|
136
|
-
- - "~>"
|
137
|
-
- !ruby/object:Gem::Version
|
138
|
-
version: '4.1'
|
139
125
|
description: ''
|
140
126
|
email:
|
141
127
|
- jun.hanamaki@gmail.com
|
@@ -160,19 +146,21 @@ files:
|
|
160
146
|
- lib/rekiq/job.rb
|
161
147
|
- lib/rekiq/middleware/utils.rb
|
162
148
|
- lib/rekiq/middleware/work_overseer.rb
|
163
|
-
- lib/rekiq/schedule_format_validator.rb
|
164
149
|
- lib/rekiq/scheduler.rb
|
150
|
+
- lib/rekiq/validator.rb
|
165
151
|
- lib/rekiq/version.rb
|
166
152
|
- lib/rekiq/worker.rb
|
167
153
|
- rekiq.gemspec
|
154
|
+
- spec/factories/configuration.rb
|
168
155
|
- spec/factories/job.rb
|
156
|
+
- spec/rekiq/configuration_spec.rb
|
169
157
|
- spec/rekiq/job_spec.rb
|
170
158
|
- spec/rekiq/middleware/utils_spec.rb
|
171
159
|
- spec/rekiq/middleware/work_overseer_spec.rb
|
172
160
|
- spec/rekiq/scheduler_spec.rb
|
173
161
|
- spec/rekiq/worker_spec.rb
|
174
162
|
- spec/spec_helper.rb
|
175
|
-
homepage:
|
163
|
+
homepage: https://github.com/junhanamaki/rekiq
|
176
164
|
licenses:
|
177
165
|
- MIT
|
178
166
|
metadata: {}
|
@@ -184,7 +172,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
184
172
|
requirements:
|
185
173
|
- - ">="
|
186
174
|
- !ruby/object:Gem::Version
|
187
|
-
version:
|
175
|
+
version: 1.9.3
|
188
176
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
189
177
|
requirements:
|
190
178
|
- - ">="
|
@@ -197,7 +185,9 @@ signing_key:
|
|
197
185
|
specification_version: 4
|
198
186
|
summary: recurring worker extension for sidekiq
|
199
187
|
test_files:
|
188
|
+
- spec/factories/configuration.rb
|
200
189
|
- spec/factories/job.rb
|
190
|
+
- spec/rekiq/configuration_spec.rb
|
201
191
|
- spec/rekiq/job_spec.rb
|
202
192
|
- spec/rekiq/middleware/utils_spec.rb
|
203
193
|
- spec/rekiq/middleware/work_overseer_spec.rb
|
@@ -1,16 +0,0 @@
|
|
1
|
-
require 'active_model'
|
2
|
-
|
3
|
-
module Rekiq
|
4
|
-
class ScheduleFormatValidator < ActiveModel::EachValidator
|
5
|
-
def validate_each(record, attribute, value)
|
6
|
-
unless value.respond_to?(:next_occurrence) and
|
7
|
-
value.method(:next_occurrence).arity.abs > 0
|
8
|
-
record.errors[attribute] <<
|
9
|
-
"invalid value for #{attribute}, value must be an object that " \
|
10
|
-
'responds to next_occurrence, and that receives at least one ' \
|
11
|
-
'argument of type Time, representing Time from which to calculate ' \
|
12
|
-
'next occurrence time'
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|