sidekiq-dejavu 0.0.3 → 0.0.5

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
- SHA1:
3
- metadata.gz: ec3f881a31547703f392561450f5377d121bd295
4
- data.tar.gz: 9b329b0b2bc47ee1265713e66dbaf84f3872661c
2
+ SHA256:
3
+ metadata.gz: a280b94512a2f87340bc0edba893acd85f65be529a212533f6dc1360bce4f9c6
4
+ data.tar.gz: f36fdd3b2aa433d0cb2f82792d2e9244ecd0957d9712657e76a114f6a2d0fa61
5
5
  SHA512:
6
- metadata.gz: e1fcd1f0d38a22fab9a7f0375ba943760a9445e51d3eb7a91b67bc73c5e30d69faeaadcf29557d09b381dc160f00c73e1f824bca5ccfa5f72cc8ef435c5bff37
7
- data.tar.gz: 7b0f0e51af703b03fd560a51dad5ff9a76c6ab43913d0e6c4f5a0d8ac41ae5fb30824eb1507cc0a9ed61bf11b3005977e7035ed0835a01769596bf4a6e634de9
6
+ metadata.gz: 3dfb6dda6f70a068d4ecc8691457d1e6e8c932f9f2729780b19522d01bdc24fa4b4be0dd8dfd4b56d9597928bf4c523057fc11f95a5baa0026e2550a808e5708
7
+ data.tar.gz: df169033e309eb1807b002171d5bb2802ee43d9085953546dcaad3338210d519782086011715aa3f13012fb75634b0a0253784d7456cf2d2591b57985a64423c
data/.travis.yml ADDED
@@ -0,0 +1,31 @@
1
+ language: ruby
2
+ sudo: false
3
+ cache: bundler
4
+ services:
5
+ - redis-server
6
+ rvm:
7
+ - 2.0.0
8
+ - 2.1.10
9
+ - 2.2.7
10
+ - 2.3.4
11
+ - 2.4.1
12
+ - jruby-1.7.26
13
+ - jruby-9.1.9.0
14
+ env:
15
+ - SIDEKIQ='~> 3.5'
16
+ - SIDEKIQ='~> 4.0'
17
+ - SIDEKIQ='~> 5.0'
18
+ matrix:
19
+ exclude:
20
+ - rvm: 2.0.0
21
+ env: SIDEKIQ='~> 5.0'
22
+ - rvm: 2.1.10
23
+ env: SIDEKIQ='~> 5.0'
24
+ - rvm: jruby-1.7.26
25
+ env: SIDEKIQ='~> 4.0'
26
+ - rvm: jruby-1.7.26
27
+ env: SIDEKIQ='~> 5.0'
28
+ - rvm: jruby-9.1.9.0
29
+ env: SIDEKIQ='~> 3.5'
30
+ - rvm: jruby-9.1.9.0
31
+ env: SIDEKIQ='~> 4.0'
data/Gemfile CHANGED
@@ -2,3 +2,9 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in sidekiq-dejavu.gemspec
4
4
  gemspec
5
+
6
+ gem "sidekiq", ENV['SIDEKIQ'] if ENV['SIDEKIQ']
7
+ gem "minitest"
8
+ gem "minitest-utils"
9
+ gem "redis-namespace"
10
+ gem "pry" unless ENV['CI']
data/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Sidekiq::Dejavu
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/sidekiq-dejavu.svg)](https://rubygems.org/gems/sidekiq-dejavu)
4
+ [![Build Status](https://travis-ci.org/felixbuenemann/sidekiq-dejavu.svg)](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
- :schedule:
50
- hello_world:
51
- interval: 10
52
- class: HelloWorldWorker
53
- queue: hello
54
- retry: false
55
- backtrace: false
56
- args:
57
- - Hello
58
- - World
59
- cleanup:
60
- interval: '30 5 * * *' # every day at 5:30
61
- class: HelloWorldWorker
62
- queue: hello
63
- retry: false
64
- backtrace: false
65
- args:
66
- - Hello
67
- - World
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
@@ -1,2 +1,9 @@
1
1
  require "bundler/gem_tasks"
2
+ require "rake/testtask"
2
3
 
4
+ Rake::TestTask.new(:test) do |test|
5
+ # test.warning = true
6
+ test.pattern = "test/**/test_*.rb"
7
+ end
8
+
9
+ task :default => :test
@@ -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
- attr_reader :schedules
6
+ attr_accessor :schedules, :scheduled_set
7
7
 
8
- def initialize(schedules)
9
- @schedules = schedules
8
+ def initialize(schedules = {}, scheduled_set = Sidekiq::ScheduledSet.new)
9
+ @schedules = deep_transform_keys_to_strings(schedules)
10
+ @scheduled_set = scheduled_set
10
11
  end
11
12
 
12
13
  def reload_schedule!
@@ -14,12 +15,31 @@ 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
 
24
+ def deep_transform_keys_to_strings(hash)
25
+ hash.each_with_object({}) do |(key, value), obj|
26
+ new_key = key.to_s
27
+ new_value = value.is_a?(Hash) ? deep_transform_keys_to_strings(value) : value
28
+ obj[new_key] = new_value
29
+ end
30
+ end
31
+
19
32
  def clear_changed_schedules
20
33
  scheduled_jobs.each do |job|
21
34
  item = job.item
22
35
  name = item['schedule']
36
+
37
+ unless schedules.has_key? name
38
+ Sidekiq.logger.info "Clearing schedule #{name} (not listed in config)."
39
+ job.delete
40
+ next
41
+ end
42
+
23
43
  schedule_options = schedules[name]
24
44
  schedule_options['args'] = Array(schedule_options['args'])
25
45
  item_options = item.select { |k,v| schedule_options.keys.include? k }
@@ -27,27 +47,25 @@ module Sidekiq
27
47
  if item_options != schedule_options
28
48
  Sidekiq.logger.info "Clearing schedule #{name} (config changed)."
29
49
  job.delete
30
- else
31
- schedules.delete(name)
32
50
  end
33
51
  end
34
52
  end
35
53
 
36
54
  def add_new_schedules
55
+ existing = scheduled_jobs.map { |job| job.item['schedule'] }
56
+
37
57
  schedules.each do |name, options|
58
+ next if existing.include? name
59
+
38
60
  args = Array(options['args'])
39
61
  interval = options['interval']
40
- first_run = next_randomized_timestamp(interval)
62
+ first_run = valid_cron?(interval) ? next_timestamp(interval) : next_randomized_timestamp(interval)
41
63
  job = options.merge('args' => args, 'schedule' => name, 'at' => first_run)
42
64
 
43
65
  Sidekiq.logger.info "Scheduling #{name} for first run at #{Time.at first_run}."
44
66
  Sidekiq::Client.push(job)
45
67
  end
46
68
  end
47
-
48
- def scheduled_jobs
49
- Sidekiq::ScheduledSet.new.select { |job| schedules.keys.include? job.item['schedule'] }
50
- end
51
69
  end
52
70
  end
53
71
  end
@@ -1,5 +1,5 @@
1
1
  module Sidekiq
2
2
  module Dejavu
3
- VERSION = "0.0.3"
3
+ VERSION = "0.0.5"
4
4
  end
5
5
  end
@@ -1,3 +1,4 @@
1
+ require "sidekiq"
1
2
  require "sidekiq/dejavu"
2
3
 
3
4
  Sidekiq.configure_server do |config|
@@ -6,7 +7,7 @@ Sidekiq.configure_server do |config|
6
7
  end
7
8
 
8
9
  config.on(:startup) do
9
- schedules = config.options[:schedule] || {}
10
+ schedules = (config.respond_to?(:[]) ? config[:schedule] : config.options[:schedule]) || {}
10
11
  Sidekiq.logger.debug "Sidekiq::Dejavu: schedules: #{schedules.inspect}"
11
12
  if schedules.empty?
12
13
  Sidekiq.logger.warn "Sidekiq::Dejavu: No schedule found."
@@ -18,8 +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.add_dependency "sidekiq", ">= 3", "< 5"
21
+ spec.add_dependency "sidekiq", ">= 3", "< 8"
22
22
  spec.add_dependency "parse-cron", "~> 0.1.4"
23
- spec.add_development_dependency "bundler", "~> 1.6"
23
+ spec.add_development_dependency "bundler"
24
24
  spec.add_development_dependency "rake"
25
25
  end
@@ -0,0 +1,6 @@
1
+ class DummyWorker
2
+ include Sidekiq::Worker
3
+ sidekiq_options :queue => :dejavu_test
4
+ def perform(*)
5
+ end
6
+ end
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
@@ -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.3
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Felix Buenemann
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-15 00:00:00.000000000 Z
11
+ date: 2024-12-03 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: '5'
22
+ version: '8'
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: '5'
32
+ version: '8'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: parse-cron
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -48,16 +48,16 @@ dependencies:
48
48
  name: bundler
49
49
  requirement: !ruby/object:Gem::Requirement
50
50
  requirements:
51
- - - "~>"
51
+ - - ">="
52
52
  - !ruby/object:Gem::Version
53
- version: '1.6'
53
+ version: '0'
54
54
  type: :development
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
- - - "~>"
58
+ - - ">="
59
59
  - !ruby/object:Gem::Version
60
- version: '1.6'
60
+ version: '0'
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: rake
63
63
  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,11 +93,15 @@ 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
98
103
  metadata: {}
99
- post_install_message:
104
+ post_install_message:
100
105
  rdoc_options: []
101
106
  require_paths:
102
107
  - lib
@@ -111,9 +116,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
111
116
  - !ruby/object:Gem::Version
112
117
  version: '0'
113
118
  requirements: []
114
- rubyforge_project:
115
- rubygems_version: 2.4.5.1
116
- signing_key:
119
+ rubygems_version: 3.1.6
120
+ signing_key:
117
121
  specification_version: 4
118
122
  summary: Dejavu is a clockless scheduler that uses Sidekiq's built-in scheduling
119
- test_files: []
123
+ test_files:
124
+ - test/fixtures/dummy_worker.rb
125
+ - test/helper.rb
126
+ - test/test_helper.rb
127
+ - test/test_manager.rb