sidekiq-dejavu 0.0.3 → 0.0.4
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/.travis.yml +19 -0
- data/Gemfile +6 -0
- data/README.md +28 -19
- data/Rakefile +7 -0
- data/lib/sidekiq-dejavu.rb +1 -0
- data/lib/sidekiq/dejavu/helper.rb +9 -1
- data/lib/sidekiq/dejavu/manager.rb +19 -9
- data/lib/sidekiq/dejavu/version.rb +1 -1
- data/sidekiq-dejavu.gemspec +1 -1
- data/test/fixtures/dummy_worker.rb +6 -0
- data/test/helper.rb +52 -0
- data/test/test_helper.rb +61 -0
- data/test/test_manager.rb +121 -0
- metadata +15 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 90086538bf6bc73e5b5a0b27034c72189c1f2221
|
4
|
+
data.tar.gz: 1a58258aef38bbf3f912cb74132c0620a337c1dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 98f4470432dfa3579a25f9ce56eb19ae56a10155c31dfc02de1d0eca73ea33950f77502f07f68aa890e280e42e5e6a8b8ddc3dca7b7bfa60b7a1b0d900203018
|
7
|
+
data.tar.gz: 75357647e815519951176b27b8ef9d1bfa58e546ce7a358f7eb6097c508c2333ec5d567c2b62a377517f655f2fda02a8803513fe880f7e98fe1c5b9ac8ca1ba4
|
data/.travis.yml
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
language: ruby
|
2
|
+
sudo: false
|
3
|
+
cache: bundler
|
4
|
+
services:
|
5
|
+
- redis-server
|
6
|
+
rvm:
|
7
|
+
- 2.1
|
8
|
+
- 2.0.0
|
9
|
+
- 2.2
|
10
|
+
- jruby
|
11
|
+
- jruby-head
|
12
|
+
- rbx-2
|
13
|
+
env:
|
14
|
+
- SIDEKIQ='~> 3.5'
|
15
|
+
- SIDEKIQ='~> 4.0'
|
16
|
+
matrix:
|
17
|
+
allow_failures:
|
18
|
+
- rvm: rbx-2
|
19
|
+
- rvm: jruby-head
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# Sidekiq::Dejavu
|
2
2
|
|
3
|
+
[](https://rubygems.org/gems/sidekiq-dejavu)
|
4
|
+
[](https://travis-ci.org/felixbuenemann/sidekiq-dejavu)
|
5
|
+
|
3
6
|
Dejavu is a clockless scheduler that uses Sidekiq's built-in scheduling.
|
4
7
|
|
5
8
|
Most scheduling solutions for Sidekiq require either a separate cron like process
|
@@ -27,6 +30,8 @@ and all re-scheduling themselves. This is because jobs get re-scheduled if there
|
|
27
30
|
schedule with the same name, but only the scheduled jobs queue is inspected.
|
28
31
|
Depending on the intervals used it is possible that the job gets scheduled and run again before
|
29
32
|
the other jobs can see the scheduled job, so they get re-scheduled as well.
|
33
|
+
- It's possible for jobs to be scheduled multiple times, if multiple processes load the same schedule
|
34
|
+
at the same time due to missing locks around loading the schedule.
|
30
35
|
|
31
36
|
## Installation
|
32
37
|
|
@@ -46,25 +51,27 @@ Or install it yourself as:
|
|
46
51
|
|
47
52
|
You can configure schedule tasks in your config/sidekiq.yml:
|
48
53
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
54
|
+
```yaml
|
55
|
+
:schedule:
|
56
|
+
hello_world:
|
57
|
+
interval: 10
|
58
|
+
class: HelloWorldWorker
|
59
|
+
queue: hello
|
60
|
+
retry: false
|
61
|
+
backtrace: false
|
62
|
+
args:
|
63
|
+
- Hello
|
64
|
+
- World
|
65
|
+
cleanup:
|
66
|
+
interval: '30 5 * * *' # every day at 5:30
|
67
|
+
class: HelloWorldWorker
|
68
|
+
queue: hello
|
69
|
+
retry: false
|
70
|
+
backtrace: false
|
71
|
+
args:
|
72
|
+
- Hello
|
73
|
+
- World
|
74
|
+
```
|
68
75
|
|
69
76
|
Interval can be specified in seconds or as a cron expression, including vixie cron syntax.
|
70
77
|
|
@@ -72,6 +79,8 @@ If a job fails or takes longer than an interval it will be retried at the next i
|
|
72
79
|
|
73
80
|
You also need to set all options for the job, because currently a workers `sidekiq_options` are ignored. The minium required options for a schedule are `interval` and `class`. The same worker can be scheduled multiple times by using different schedule names (keys) in the config.
|
74
81
|
|
82
|
+
Note that by default sidekiq polls scheduled jobs roughly every 15 seconds, which means in order to run jobs at shorter intervals youd'd have to tune `config.average_scheduled_poll_interval` to a lower value.
|
83
|
+
|
75
84
|
## Contributing
|
76
85
|
|
77
86
|
1. Fork it ( https://github.com/felixbuenemann/sidekiq-dejavu/fork )
|
data/Rakefile
CHANGED
data/lib/sidekiq-dejavu.rb
CHANGED
@@ -3,6 +3,13 @@ require 'parse-cron'
|
|
3
3
|
module Sidekiq
|
4
4
|
module Dejavu
|
5
5
|
module Helper
|
6
|
+
def valid_cron?(interval)
|
7
|
+
CronParser.new(interval)
|
8
|
+
true
|
9
|
+
rescue ArgumentError
|
10
|
+
false
|
11
|
+
end
|
12
|
+
|
6
13
|
def next_timestamp(interval, time = Time.now)
|
7
14
|
CronParser.new(interval).next(time).to_f
|
8
15
|
rescue ArgumentError
|
@@ -10,7 +17,8 @@ module Sidekiq
|
|
10
17
|
end
|
11
18
|
|
12
19
|
def next_randomized_timestamp(interval, time = Time.now)
|
13
|
-
CronParser.new(interval).next(time).to_f
|
20
|
+
diff = CronParser.new(interval).next(time).to_f - time.to_f
|
21
|
+
time.to_f + Random.rand(diff)
|
14
22
|
rescue ArgumentError
|
15
23
|
time.to_f + Random.rand(interval.to_f)
|
16
24
|
end
|
@@ -3,10 +3,11 @@ module Sidekiq
|
|
3
3
|
class Manager
|
4
4
|
include Helper
|
5
5
|
|
6
|
-
|
6
|
+
attr_accessor :schedules, :scheduled_set
|
7
7
|
|
8
|
-
def initialize(schedules)
|
8
|
+
def initialize(schedules = {}, scheduled_set = Sidekiq::ScheduledSet.new)
|
9
9
|
@schedules = schedules
|
10
|
+
@scheduled_set = scheduled_set
|
10
11
|
end
|
11
12
|
|
12
13
|
def reload_schedule!
|
@@ -14,12 +15,23 @@ module Sidekiq
|
|
14
15
|
add_new_schedules
|
15
16
|
end
|
16
17
|
|
18
|
+
def scheduled_jobs
|
19
|
+
scheduled_set.select { |job| job.item.has_key? 'schedule' }
|
20
|
+
end
|
21
|
+
|
17
22
|
private
|
18
23
|
|
19
24
|
def clear_changed_schedules
|
20
25
|
scheduled_jobs.each do |job|
|
21
26
|
item = job.item
|
22
27
|
name = item['schedule']
|
28
|
+
|
29
|
+
unless schedules.has_key? name
|
30
|
+
Sidekiq.logger.info "Clearing schedule #{name} (not listed in config)."
|
31
|
+
job.delete
|
32
|
+
next
|
33
|
+
end
|
34
|
+
|
23
35
|
schedule_options = schedules[name]
|
24
36
|
schedule_options['args'] = Array(schedule_options['args'])
|
25
37
|
item_options = item.select { |k,v| schedule_options.keys.include? k }
|
@@ -27,27 +39,25 @@ module Sidekiq
|
|
27
39
|
if item_options != schedule_options
|
28
40
|
Sidekiq.logger.info "Clearing schedule #{name} (config changed)."
|
29
41
|
job.delete
|
30
|
-
else
|
31
|
-
schedules.delete(name)
|
32
42
|
end
|
33
43
|
end
|
34
44
|
end
|
35
45
|
|
36
46
|
def add_new_schedules
|
47
|
+
existing = scheduled_jobs.map { |job| job.item['schedule'] }
|
48
|
+
|
37
49
|
schedules.each do |name, options|
|
50
|
+
next if existing.include? name
|
51
|
+
|
38
52
|
args = Array(options['args'])
|
39
53
|
interval = options['interval']
|
40
|
-
first_run = next_randomized_timestamp(interval)
|
54
|
+
first_run = valid_cron?(interval) ? next_timestamp(interval) : next_randomized_timestamp(interval)
|
41
55
|
job = options.merge('args' => args, 'schedule' => name, 'at' => first_run)
|
42
56
|
|
43
57
|
Sidekiq.logger.info "Scheduling #{name} for first run at #{Time.at first_run}."
|
44
58
|
Sidekiq::Client.push(job)
|
45
59
|
end
|
46
60
|
end
|
47
|
-
|
48
|
-
def scheduled_jobs
|
49
|
-
Sidekiq::ScheduledSet.new.select { |job| schedules.keys.include? job.item['schedule'] }
|
50
|
-
end
|
51
61
|
end
|
52
62
|
end
|
53
63
|
end
|
data/sidekiq-dejavu.gemspec
CHANGED
@@ -18,7 +18,7 @@ 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.add_dependency "sidekiq", ">= 3", "<
|
21
|
+
spec.add_dependency "sidekiq", ">= 3", "< 6"
|
22
22
|
spec.add_dependency "parse-cron", "~> 0.1.4"
|
23
23
|
spec.add_development_dependency "bundler", "~> 1.6"
|
24
24
|
spec.add_development_dependency "rake"
|
data/test/helper.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# disable minitest/parallel threads
|
2
|
+
ENV["N"] = "0"
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
|
6
|
+
require "sidekiq"
|
7
|
+
require "sidekiq/api"
|
8
|
+
require "sidekiq/testing"
|
9
|
+
|
10
|
+
require "minitest/autorun"
|
11
|
+
require "yaml"
|
12
|
+
require "pry" unless ENV['CI']
|
13
|
+
|
14
|
+
require "sidekiq/dejavu"
|
15
|
+
|
16
|
+
require_relative "fixtures/dummy_worker"
|
17
|
+
|
18
|
+
require 'sidekiq/redis_connection'
|
19
|
+
REDIS_URL = ENV['REDIS_URL'] || 'redis://localhost/15'
|
20
|
+
REDIS = Sidekiq::RedisConnection.create(:url => REDIS_URL, :namespace => 'dejavu_test')
|
21
|
+
|
22
|
+
Sidekiq.configure_client do |config|
|
23
|
+
config.redis = { :url => REDIS_URL, :namespace => 'dejavu_test' }
|
24
|
+
end
|
25
|
+
|
26
|
+
Sidekiq::Testing.disable!
|
27
|
+
Sidekiq::Testing.server_middleware do |chain|
|
28
|
+
chain.add Sidekiq::Dejavu::Middleware::Server::Scheduler
|
29
|
+
end
|
30
|
+
|
31
|
+
class Sidekiq::Dejavu::Test < MiniTest::Test
|
32
|
+
attr_reader :log, :scheduled_set
|
33
|
+
|
34
|
+
def setup
|
35
|
+
# capture logger
|
36
|
+
@old_logger = Sidekiq.logger
|
37
|
+
@log = StringIO.new
|
38
|
+
Sidekiq.logger = Logger.new(@log)
|
39
|
+
# clear scheduled set
|
40
|
+
@scheduled_set = Sidekiq::ScheduledSet.new
|
41
|
+
@scheduled_set.clear
|
42
|
+
end
|
43
|
+
|
44
|
+
def teardown
|
45
|
+
Sidekiq::Worker.drain_all
|
46
|
+
Sidekiq.logger = @old_logger
|
47
|
+
end
|
48
|
+
|
49
|
+
def assert_logged(regex)
|
50
|
+
assert_match log, regex
|
51
|
+
end
|
52
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require_relative "helper"
|
2
|
+
|
3
|
+
class TestHelper < Sidekiq::Dejavu::Test
|
4
|
+
include Sidekiq::Dejavu::Helper
|
5
|
+
|
6
|
+
def time
|
7
|
+
@time ||= Time.now
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_valid_cron_with_valid_cron
|
11
|
+
interval = '* * * * *'
|
12
|
+
assert_equal true, valid_cron?(interval)
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_valid_cron_with_interval
|
16
|
+
[10, 10.0, '10', '10.0'].each do |interval|
|
17
|
+
assert_equal false, valid_cron?(interval)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_valid_cron_with_garbage
|
22
|
+
interval = 'garbage'
|
23
|
+
assert_equal false, valid_cron?(interval)
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_next_timestamp_cron
|
27
|
+
interval = '* * * * *'
|
28
|
+
expected = time.to_f + (60 - time.to_f % 60)
|
29
|
+
assert_equal expected, next_timestamp(interval, time)
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_next_timestamp_numeric
|
33
|
+
expected = time.to_f + 10.0
|
34
|
+
[10, 10.0, '10', '10.0'].each do |interval|
|
35
|
+
assert_equal expected, next_timestamp(interval, time)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_next_randomized_timestamp_cron
|
40
|
+
interval = '* * * * *'
|
41
|
+
expected = time.to_f + (60 - time.to_f % 60)
|
42
|
+
timestamp = next_randomized_timestamp(interval, time)
|
43
|
+
another_timestamp = next_randomized_timestamp(interval, time)
|
44
|
+
|
45
|
+
assert_in_delta expected, timestamp, 60.0
|
46
|
+
refute_equal expected, timestamp
|
47
|
+
refute_equal timestamp, another_timestamp
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_next_randomized_timestamp_numeric
|
51
|
+
expected = time.to_f + 10.0
|
52
|
+
[10, 10.0, '10', '10.0'].each do |interval|
|
53
|
+
timestamp = next_randomized_timestamp(interval, time)
|
54
|
+
another_timestamp = next_randomized_timestamp(interval, time)
|
55
|
+
|
56
|
+
assert_in_delta expected, timestamp, 10.0
|
57
|
+
refute_equal expected, timestamp
|
58
|
+
refute_equal timestamp, another_timestamp
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require_relative "helper"
|
2
|
+
|
3
|
+
class TestManager < Sidekiq::Dejavu::Test
|
4
|
+
def schedules
|
5
|
+
@schedules ||= YAML.load(<<-YAML).freeze
|
6
|
+
foo:
|
7
|
+
interval: 10
|
8
|
+
class: DummyWorker
|
9
|
+
args:
|
10
|
+
- fooarg
|
11
|
+
bar:
|
12
|
+
interval: '30 5 * * *'
|
13
|
+
class: DummyWorker
|
14
|
+
args:
|
15
|
+
- bararg
|
16
|
+
YAML
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_reload_schedule!
|
20
|
+
manager = Sidekiq::Dejavu::Manager.new schedules
|
21
|
+
|
22
|
+
assert_equal 0, scheduled_set.size
|
23
|
+
manager.reload_schedule!
|
24
|
+
assert_equal 2, scheduled_set.size
|
25
|
+
|
26
|
+
foo = scheduled_set.find { |job| job.item['schedule'] == 'foo' }
|
27
|
+
assert foo
|
28
|
+
assert_equal 10, foo.item['interval']
|
29
|
+
assert_equal 'DummyWorker', foo.item['class']
|
30
|
+
assert_equal %w(fooarg), foo.item['args']
|
31
|
+
|
32
|
+
bar = scheduled_set.find { |job| job.item['schedule'] == 'bar' }
|
33
|
+
assert bar
|
34
|
+
assert_equal '30 5 * * *', bar.item['interval']
|
35
|
+
assert_equal 'DummyWorker', bar.item['class']
|
36
|
+
assert_equal %w(bararg), bar.item['args']
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_reload_schedule_clears_old_schedules
|
40
|
+
old_schedules = YAML.load <<-YAML
|
41
|
+
old:
|
42
|
+
interval: 15
|
43
|
+
class: DummyWorker
|
44
|
+
YAML
|
45
|
+
|
46
|
+
manager = Sidekiq::Dejavu::Manager.new old_schedules
|
47
|
+
assert_equal 0, scheduled_set.size
|
48
|
+
manager.reload_schedule!
|
49
|
+
assert_equal 1, scheduled_set.size
|
50
|
+
|
51
|
+
assert scheduled_set.find { |job| job.item['schedule'] == 'old' }
|
52
|
+
|
53
|
+
manager.schedules = {}
|
54
|
+
assert_equal 1, scheduled_set.size
|
55
|
+
manager.reload_schedule!
|
56
|
+
assert_equal 0, scheduled_set.size
|
57
|
+
|
58
|
+
refute scheduled_set.find { |job| job.item['schedule'] == 'old' }
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_reload_schedule_updates_existing_schedules
|
62
|
+
old_schedules = YAML.load <<-YAML
|
63
|
+
foo:
|
64
|
+
interval: 15
|
65
|
+
class: DummyWorker
|
66
|
+
args:
|
67
|
+
- oldfooarg
|
68
|
+
bar:
|
69
|
+
interval: '15 4 * * *'
|
70
|
+
class: DummyWorker
|
71
|
+
args:
|
72
|
+
- oldbararg
|
73
|
+
YAML
|
74
|
+
|
75
|
+
manager = Sidekiq::Dejavu::Manager.new old_schedules
|
76
|
+
|
77
|
+
assert_equal 0, scheduled_set.size
|
78
|
+
manager.reload_schedule!
|
79
|
+
assert_equal 2, scheduled_set.size
|
80
|
+
|
81
|
+
foo = scheduled_set.find { |job| job.item['schedule'] == 'foo' }
|
82
|
+
assert foo
|
83
|
+
assert_equal 15, foo.item['interval']
|
84
|
+
assert_equal 'DummyWorker', foo.item['class']
|
85
|
+
assert_equal %w(oldfooarg), foo.item['args']
|
86
|
+
|
87
|
+
bar = scheduled_set.find { |job| job.item['schedule'] == 'bar' }
|
88
|
+
assert bar
|
89
|
+
assert_equal '15 4 * * *', bar.item['interval']
|
90
|
+
assert_equal 'DummyWorker', bar.item['class']
|
91
|
+
assert_equal %w(oldbararg), bar.item['args']
|
92
|
+
|
93
|
+
manager.schedules = schedules
|
94
|
+
assert_equal 2, scheduled_set.size
|
95
|
+
manager.reload_schedule!
|
96
|
+
assert_equal 2, scheduled_set.size
|
97
|
+
|
98
|
+
foo = scheduled_set.find { |job| job.item['schedule'] == 'foo' }
|
99
|
+
assert foo
|
100
|
+
assert_equal 10, foo.item['interval']
|
101
|
+
assert_equal 'DummyWorker', foo.item['class']
|
102
|
+
assert_equal %w(fooarg), foo.item['args']
|
103
|
+
|
104
|
+
bar = scheduled_set.find { |job| job.item['schedule'] == 'bar' }
|
105
|
+
assert bar
|
106
|
+
assert_equal '30 5 * * *', bar.item['interval']
|
107
|
+
assert_equal 'DummyWorker', bar.item['class']
|
108
|
+
assert_equal %w(bararg), bar.item['args']
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_reload_schedule_keeps_unchanged_schedules
|
112
|
+
manager = Sidekiq::Dejavu::Manager.new schedules
|
113
|
+
assert_equal 0, scheduled_set.size
|
114
|
+
manager.reload_schedule!
|
115
|
+
assert_equal 2, scheduled_set.size
|
116
|
+
|
117
|
+
manager.schedules = schedules
|
118
|
+
manager.reload_schedule!
|
119
|
+
assert_equal 2, scheduled_set.size
|
120
|
+
end
|
121
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sidekiq-dejavu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Felix Buenemann
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-06-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sidekiq
|
@@ -19,7 +19,7 @@ dependencies:
|
|
19
19
|
version: '3'
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: '
|
22
|
+
version: '6'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -29,7 +29,7 @@ dependencies:
|
|
29
29
|
version: '3'
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
32
|
+
version: '6'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: parse-cron
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -81,6 +81,7 @@ extensions: []
|
|
81
81
|
extra_rdoc_files: []
|
82
82
|
files:
|
83
83
|
- ".gitignore"
|
84
|
+
- ".travis.yml"
|
84
85
|
- Gemfile
|
85
86
|
- LICENSE.txt
|
86
87
|
- README.md
|
@@ -92,6 +93,10 @@ files:
|
|
92
93
|
- lib/sidekiq/dejavu/middleware/server/scheduler.rb
|
93
94
|
- lib/sidekiq/dejavu/version.rb
|
94
95
|
- sidekiq-dejavu.gemspec
|
96
|
+
- test/fixtures/dummy_worker.rb
|
97
|
+
- test/helper.rb
|
98
|
+
- test/test_helper.rb
|
99
|
+
- test/test_manager.rb
|
95
100
|
homepage: https://github.com/felixbuenemann/sidekiq-dejavu
|
96
101
|
licenses:
|
97
102
|
- MIT
|
@@ -112,8 +117,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
112
117
|
version: '0'
|
113
118
|
requirements: []
|
114
119
|
rubyforge_project:
|
115
|
-
rubygems_version: 2.
|
120
|
+
rubygems_version: 2.6.12
|
116
121
|
signing_key:
|
117
122
|
specification_version: 4
|
118
123
|
summary: Dejavu is a clockless scheduler that uses Sidekiq's built-in scheduling
|
119
|
-
test_files:
|
124
|
+
test_files:
|
125
|
+
- test/fixtures/dummy_worker.rb
|
126
|
+
- test/helper.rb
|
127
|
+
- test/test_helper.rb
|
128
|
+
- test/test_manager.rb
|