sqeduler 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +4 -0
- data/README.md +9 -2
- data/lib/sqeduler/config.rb +2 -1
- data/lib/sqeduler/lock_maintainer.rb +82 -0
- data/lib/sqeduler/redis_scripts.rb +7 -6
- data/lib/sqeduler/service.rb +4 -6
- data/lib/sqeduler/version.rb +1 -1
- data/lib/sqeduler/worker/kill_switch.rb +1 -1
- data/lib/sqeduler/worker/synchronization.rb +9 -9
- data/lib/sqeduler.rb +1 -0
- data/spec/fixtures/empty_schedule.yaml +1 -0
- data/spec/fixtures/env.rb +5 -6
- data/spec/fixtures/fake_worker.rb +6 -6
- data/spec/lock_maintainer_spec.rb +140 -0
- data/spec/spec_helper.rb +2 -5
- data/sqeduler.gemspec +1 -1
- metadata +10 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9331eead88bcd85bcd8e564ce22b5de81b3a43ee
|
4
|
+
data.tar.gz: b2ae466592349be888d1ff930f344e1b32702587
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0b7af459f6a789931ad6a078650449e3efe51641f3b863206a9c99283740bb636010ecc581abd946027773f14fa16f820f1fb6df2cfb90b9476b8f9c2a913109
|
7
|
+
data.tar.gz: 416c4d0f6c7059fbd40e5aeb8495b46c25f67f919e314196c1df4a8313dd0475d6ea159c229dede39015b282f9ce987c7078bdbf9894494704096412caf47019
|
data/CHANGES.md
CHANGED
data/README.md
CHANGED
@@ -19,11 +19,10 @@ Provides loosely-coupled helpers for Sidekiq workers. Provides highly available
|
|
19
19
|
|
20
20
|
## Examples
|
21
21
|
|
22
|
-
To install this gem
|
22
|
+
To install this gem, add it to your Gemfile:
|
23
23
|
|
24
24
|
```ruby
|
25
25
|
gem 'sqeduler'
|
26
|
-
gem 'sidekiq-scheduler', :github => 'ecin/sidekiq-scheduler', :branch => 'ecin/redis-lock' # https://github.com/Moove-it/sidekiq-scheduler/pull/38
|
27
26
|
```
|
28
27
|
|
29
28
|
### Scheduling
|
@@ -48,6 +47,8 @@ config.on_server_start = proc {|config| ... }
|
|
48
47
|
config.on_client_start = proc {|config| ... }
|
49
48
|
# required if you want to start the Sidekiq::Scheduler
|
50
49
|
config.schedule_path = Rails.root.join('config').join('sidekiq_schedule.yml')
|
50
|
+
# optional to maintain locks for exclusive jobs, see "Lock Maintainer" below
|
51
|
+
config.maintain_locks = true
|
51
52
|
|
52
53
|
Sqeduler::Service.config = config
|
53
54
|
# Starts Sidekiq and Sidekiq::Scheduler
|
@@ -57,6 +58,12 @@ Sqeduler::Service.start
|
|
57
58
|
See documentation for [Sidekiq::Scheduler](https://github.com/Moove-it/sidekiq-scheduler#scheduled-jobs-recurring-jobs)
|
58
59
|
for specifics on how to construct your schedule YAML file.
|
59
60
|
|
61
|
+
### Lock Maintainer
|
62
|
+
|
63
|
+
Exclusive locks only last for the expiration you set. If your expiration is 30 seconds and the job runs for 60 seconds, you can have multiple jobs running at once. Rather than having to set absurdly high lock expirations, you can enable the `maintain_locks` option which handles this for you.
|
64
|
+
|
65
|
+
Every 30 seconds, Sqeduler will look for any exclusive Sidekiq jobs that have been running for more than 30 seconds, and have a lock expiration of more than 30 seconds and refresh the lock.
|
66
|
+
|
60
67
|
### Worker Helpers
|
61
68
|
|
62
69
|
To use `Sqeduler::Worker` modules:
|
data/lib/sqeduler/config.rb
CHANGED
@@ -3,7 +3,7 @@ module Sqeduler
|
|
3
3
|
# Simple config for Sqeduler::Service
|
4
4
|
class Config
|
5
5
|
attr_accessor :logger, :redis_hash, :schedule_path,
|
6
|
-
:on_server_start, :on_client_start
|
6
|
+
:on_server_start, :on_client_start, :maintain_locks
|
7
7
|
|
8
8
|
def initialize(opts = {})
|
9
9
|
self.redis_hash = opts[:redis_hash]
|
@@ -11,6 +11,7 @@ module Sqeduler
|
|
11
11
|
self.on_server_start = opts[:on_server_start]
|
12
12
|
self.on_client_start = opts[:on_client_start]
|
13
13
|
self.logger = opts[:logger]
|
14
|
+
self.maintain_locks = opts[:maintain_locks]
|
14
15
|
end
|
15
16
|
end
|
16
17
|
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Sqeduler
|
3
|
+
# This is to ensure that if you set your jobs to run one a time and something goes wrong
|
4
|
+
# causing a job to run for a long time, your lock won't expire.
|
5
|
+
# This doesn't stop long running jobs, it just ensures you only end up with one long running job
|
6
|
+
# rather than 20 of them.
|
7
|
+
class LockMaintainer
|
8
|
+
RUN_INTERVAL = 30
|
9
|
+
RUN_JITTER = 1..5
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@class_with_locks = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
# This is only done when we initialize Sqeduler, don't need to worry about threading
|
16
|
+
def run
|
17
|
+
@maintainer_thread ||= Thread.new do
|
18
|
+
loop do
|
19
|
+
begin
|
20
|
+
synchronize
|
21
|
+
rescue => ex
|
22
|
+
Service.logger.error "[SQEDULER LOCK MAINTAINER] #{ex.class}, #{ex.message}"
|
23
|
+
end
|
24
|
+
|
25
|
+
sleep RUN_INTERVAL + rand(RUN_JITTER)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def synchronize
|
33
|
+
# Not great, but finding our identity in Sidekiq is a pain, and we already have locks in Sqeduler.
|
34
|
+
# Easier to just try and grab a lock each time and whichever server wins gets to do it.
|
35
|
+
return unless redis_lock.send(:take_lock)
|
36
|
+
|
37
|
+
now = Time.now.to_i
|
38
|
+
|
39
|
+
Service.redis_pool do |redis|
|
40
|
+
redis.pipelined do
|
41
|
+
workers.each do |_worker, _tid, args|
|
42
|
+
# No sense in pinging if it's not been running long enough to matter
|
43
|
+
next if (now - args["run_at"]) < RUN_INTERVAL
|
44
|
+
|
45
|
+
klass = str_to_class(args["payload"]["class"])
|
46
|
+
next unless klass
|
47
|
+
|
48
|
+
lock_key = klass.sync_lock_key(*args["payload"]["args"])
|
49
|
+
|
50
|
+
# This works because EXPIRE does not recreate the key, it only resets the expiration.
|
51
|
+
# We don't have to worry about atomic operations or anything like that.
|
52
|
+
# If the job finishes in the interim and deletes the key nothing will happen.
|
53
|
+
redis.expire(lock_key, klass.synchronize_jobs_expiration)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Not all classes will use exclusive locks
|
60
|
+
def str_to_class(class_name)
|
61
|
+
return @class_with_locks[class_name] unless @class_with_locks[class_name].nil?
|
62
|
+
|
63
|
+
klass = class_name.constantize
|
64
|
+
if klass.respond_to?(:synchronize_jobs_mode)
|
65
|
+
# We only care about exclusive jobs that are long running
|
66
|
+
if klass.synchronize_jobs_mode == :one_at_a_time && klass.synchronize_jobs_timeout >= RUN_INTERVAL
|
67
|
+
return @class_with_locks[class_name] = klass
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
@class_with_locks[class_name] = false
|
72
|
+
end
|
73
|
+
|
74
|
+
def redis_lock
|
75
|
+
@redis_lock ||= RedisLock.new("sqeduler-lock-maintainer", :expiration => 60, :timeout => 0)
|
76
|
+
end
|
77
|
+
|
78
|
+
def workers
|
79
|
+
@workers ||= Sidekiq::Workers.new
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -23,12 +23,13 @@ module Sqeduler
|
|
23
23
|
def load_sha(redis, script_name)
|
24
24
|
@redis_sha_cache ||= {}
|
25
25
|
@redis_sha_cache[script_name] ||= begin
|
26
|
-
script =
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
26
|
+
script = case script_name
|
27
|
+
when :refresh
|
28
|
+
refresh_lock_script
|
29
|
+
when :release
|
30
|
+
release_lock_script
|
31
|
+
else
|
32
|
+
fail "No script for #{script_name}"
|
32
33
|
end
|
33
34
|
# strip leading whitespace of 8 characters
|
34
35
|
redis.script(:load, script.gsub(/^ {8}/, ""))
|
data/lib/sqeduler/service.rb
CHANGED
@@ -5,7 +5,7 @@ module Sqeduler
|
|
5
5
|
# Singleton class for configuring this Gem.
|
6
6
|
class Service
|
7
7
|
SCHEDULER_TIMEOUT = 60
|
8
|
-
MINIMUM_REDIS_VERSION = "2.6.12"
|
8
|
+
MINIMUM_REDIS_VERSION = "2.6.12".freeze
|
9
9
|
|
10
10
|
class << self
|
11
11
|
attr_accessor :config
|
@@ -44,6 +44,7 @@ module Sqeduler
|
|
44
44
|
chain.add(Sqeduler::Middleware::KillSwitch)
|
45
45
|
end
|
46
46
|
|
47
|
+
LockMaintainer.new.run if Service.config.maintain_locks
|
47
48
|
Service.config.on_server_start.call(config) if Service.config.on_server_start
|
48
49
|
end
|
49
50
|
end
|
@@ -104,11 +105,8 @@ module Sqeduler
|
|
104
105
|
|
105
106
|
def logger
|
106
107
|
return config.logger if config.logger
|
107
|
-
if defined?(Rails)
|
108
|
-
|
109
|
-
else
|
110
|
-
fail ArgumentError, "No logger provided and Rails.logger cannot be inferred"
|
111
|
-
end
|
108
|
+
return Rails.logger if defined?(Rails)
|
109
|
+
fail ArgumentError, "No logger provided and Rails.logger cannot be inferred"
|
112
110
|
end
|
113
111
|
end
|
114
112
|
end
|
data/lib/sqeduler/version.rb
CHANGED
@@ -3,7 +3,7 @@ module Sqeduler
|
|
3
3
|
module Worker
|
4
4
|
# Uses Redis hashes to enabled and disable workers across multiple hosts.
|
5
5
|
module KillSwitch
|
6
|
-
SIDEKIQ_DISABLED_WORKERS = "sidekiq.disabled-workers"
|
6
|
+
SIDEKIQ_DISABLED_WORKERS = "sidekiq.disabled-workers".freeze
|
7
7
|
|
8
8
|
def self.prepended(base)
|
9
9
|
if base.ancestors.include?(Sqeduler::Worker::Callbacks)
|
@@ -27,12 +27,20 @@ module Sqeduler
|
|
27
27
|
return if synchronize_jobs_expiration
|
28
28
|
fail ArgumentError, ":expiration is required!"
|
29
29
|
end
|
30
|
+
|
31
|
+
def sync_lock_key(*args)
|
32
|
+
if args.empty?
|
33
|
+
name
|
34
|
+
else
|
35
|
+
"#{name}-#{args.join}"
|
36
|
+
end
|
37
|
+
end
|
30
38
|
end
|
31
39
|
# rubocop:enable Style/Documentation
|
32
40
|
|
33
41
|
def perform(*args)
|
34
42
|
if self.class.synchronize_jobs_mode == :one_at_a_time
|
35
|
-
perform_locked(sync_lock_key(*args)) do
|
43
|
+
perform_locked(self.class.sync_lock_key(*args)) do
|
36
44
|
perform_timed do
|
37
45
|
super
|
38
46
|
end
|
@@ -44,14 +52,6 @@ module Sqeduler
|
|
44
52
|
|
45
53
|
private
|
46
54
|
|
47
|
-
def sync_lock_key(*args)
|
48
|
-
if args.empty?
|
49
|
-
self.class.name
|
50
|
-
else
|
51
|
-
"#{self.class.name}-#{args.join}"
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
55
|
# callback for when a lock cannot be obtained
|
56
56
|
def on_lock_timeout(key)
|
57
57
|
Service.logger.warn(
|
data/lib/sqeduler.rb
CHANGED
@@ -6,6 +6,7 @@ require "sqeduler/redis_scripts"
|
|
6
6
|
require "sqeduler/lock_value"
|
7
7
|
require "sqeduler/redis_lock"
|
8
8
|
require "sqeduler/trigger_lock"
|
9
|
+
require "sqeduler/lock_maintainer"
|
9
10
|
require "sqeduler/middleware/kill_switch"
|
10
11
|
require "sqeduler/service"
|
11
12
|
require "sqeduler/worker/callbacks"
|
@@ -0,0 +1 @@
|
|
1
|
+
{}
|
data/spec/fixtures/env.rb
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
require "sqeduler"
|
2
2
|
require_relative "fake_worker"
|
3
3
|
|
4
|
-
REDIS_CONFIG = {
|
5
|
-
:host => "localhost",
|
6
|
-
:db => 1,
|
7
|
-
:namespace => "sqeduler-tests"
|
8
|
-
}
|
9
4
|
Sidekiq.logger = Logger.new(STDOUT).tap { |l| l.level = Logger::DEBUG }
|
10
5
|
|
11
6
|
Sqeduler::Service.config = Sqeduler::Config.new(
|
12
|
-
:redis_hash =>
|
7
|
+
:redis_hash => {
|
8
|
+
:host => "localhost",
|
9
|
+
:db => 1,
|
10
|
+
:namespace => "sqeduler-tests"
|
11
|
+
},
|
13
12
|
:logger => Sidekiq.logger,
|
14
13
|
:schedule_path => File.expand_path(File.dirname(__FILE__)) + "/schedule.yaml",
|
15
14
|
:on_server_start => proc do |_config|
|
@@ -1,12 +1,12 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
# Sample worker for specs
|
3
3
|
class FakeWorker
|
4
|
-
JOB_RUN_PATH = "/tmp/job_run"
|
5
|
-
JOB_BEFORE_START_PATH = "/tmp/job_before_start"
|
6
|
-
JOB_SUCCESS_PATH = "/tmp/job_success"
|
7
|
-
JOB_FAILURE_PATH = "/tmp/job_failure"
|
8
|
-
JOB_LOCK_FAILURE_PATH = "/tmp/lock_failure"
|
9
|
-
SCHEDULE_COLLISION_PATH = "/tmp/schedule_collision"
|
4
|
+
JOB_RUN_PATH = "/tmp/job_run".freeze
|
5
|
+
JOB_BEFORE_START_PATH = "/tmp/job_before_start".freeze
|
6
|
+
JOB_SUCCESS_PATH = "/tmp/job_success".freeze
|
7
|
+
JOB_FAILURE_PATH = "/tmp/job_failure".freeze
|
8
|
+
JOB_LOCK_FAILURE_PATH = "/tmp/lock_failure".freeze
|
9
|
+
SCHEDULE_COLLISION_PATH = "/tmp/schedule_collision".freeze
|
10
10
|
include Sidekiq::Worker
|
11
11
|
include Sqeduler::Worker::Everything
|
12
12
|
|
@@ -0,0 +1,140 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
RSpec.describe Sqeduler::LockMaintainer do
|
5
|
+
let(:instance) { described_class.new }
|
6
|
+
|
7
|
+
before do
|
8
|
+
stub_const(
|
9
|
+
"SyncExclusiveWorker",
|
10
|
+
Class.new do
|
11
|
+
include Sidekiq::Worker
|
12
|
+
prepend Sqeduler::Worker::Synchronization
|
13
|
+
synchronize :one_at_a_time, :expiration => 300, :timeout => 30
|
14
|
+
|
15
|
+
def perform(*_args)
|
16
|
+
yield
|
17
|
+
end
|
18
|
+
end
|
19
|
+
)
|
20
|
+
|
21
|
+
stub_const(
|
22
|
+
"SyncWhateverWorker",
|
23
|
+
Class.new do
|
24
|
+
include Sidekiq::Worker
|
25
|
+
prepend Sqeduler::Worker::Synchronization
|
26
|
+
|
27
|
+
def perform
|
28
|
+
fail "This shouldn't be called"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
)
|
32
|
+
|
33
|
+
Sqeduler::Service.config = Sqeduler::Config.new(
|
34
|
+
:redis_hash => REDIS_CONFIG,
|
35
|
+
:logger => Logger.new("/dev/null"),
|
36
|
+
:schedule_path => Pathname.new("./spec/fixtures/empty_schedule.yaml")
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
context "#run" do
|
41
|
+
let(:run) { instance.run }
|
42
|
+
|
43
|
+
it "calls into the synchronizer" do
|
44
|
+
expect(instance).to receive(:synchronize).at_least(1)
|
45
|
+
|
46
|
+
run.join(1)
|
47
|
+
run.terminate
|
48
|
+
end
|
49
|
+
|
50
|
+
it "doesn't die on errors" do
|
51
|
+
expect(instance).to receive(:synchronize).and_raise(StandardError, "Boom")
|
52
|
+
|
53
|
+
run.join(1)
|
54
|
+
expect(run.status).to_not be_falsy
|
55
|
+
run.terminate
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context "#synchronize" do
|
60
|
+
subject(:sync) { instance.send(:synchronize) }
|
61
|
+
|
62
|
+
let(:run_at) { Time.now.to_i }
|
63
|
+
let(:job_args) { [1, { "a" => "b" }] }
|
64
|
+
|
65
|
+
let(:workers) do
|
66
|
+
[
|
67
|
+
[
|
68
|
+
"process-key",
|
69
|
+
"worker-tid-1234",
|
70
|
+
{
|
71
|
+
"run_at" => run_at,
|
72
|
+
"payload" => {
|
73
|
+
"class" => "SyncExclusiveWorker",
|
74
|
+
"args" => job_args
|
75
|
+
}
|
76
|
+
}
|
77
|
+
],
|
78
|
+
[
|
79
|
+
"process-key",
|
80
|
+
"worker-tid-4321",
|
81
|
+
{
|
82
|
+
"run_at" => run_at,
|
83
|
+
"payload" => {
|
84
|
+
"class" => "SyncWhateverWorker",
|
85
|
+
"args" => []
|
86
|
+
}
|
87
|
+
}
|
88
|
+
]
|
89
|
+
]
|
90
|
+
end
|
91
|
+
|
92
|
+
before { allow(instance).to receive(:workers).and_return(workers) }
|
93
|
+
|
94
|
+
it "does nothing if the jobs just started" do
|
95
|
+
expect(instance).to_not receive(:str_to_class)
|
96
|
+
sync
|
97
|
+
end
|
98
|
+
|
99
|
+
context "when outside the run threshold" do
|
100
|
+
let(:run_at) { Time.now - described_class::RUN_INTERVAL - 5 }
|
101
|
+
|
102
|
+
let(:lock_key) { SyncExclusiveWorker.sync_lock_key(job_args) }
|
103
|
+
|
104
|
+
it "refresh the lock" do
|
105
|
+
SyncExclusiveWorker.new.perform(job_args) do
|
106
|
+
Sqeduler::Service.redis_pool do |redis|
|
107
|
+
# Change the lock timing to make sure ours works
|
108
|
+
redis.expire(lock_key, 10)
|
109
|
+
expect(redis.ttl(lock_key)).to eq(10)
|
110
|
+
|
111
|
+
# Run the re-locker
|
112
|
+
sync
|
113
|
+
|
114
|
+
# Confirm it reset
|
115
|
+
expect(redis.ttl(lock_key)).to eq(300)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# Shouldn't be around once the job finished
|
120
|
+
Sqeduler::Service.redis_pool do |redis|
|
121
|
+
expect(redis.exists(lock_key)).to eq(false)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
it "obeys the exclusive lock" do
|
126
|
+
instance.send(:redis_lock).send(:take_lock)
|
127
|
+
expect(instance).to_not receive(:str_to_class)
|
128
|
+
|
129
|
+
sync
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context "#str_to_class" do
|
135
|
+
it "only returns exclusive lock classes" do
|
136
|
+
expect(instance.send(:str_to_class, "SyncExclusiveWorker")).to eq(SyncExclusiveWorker)
|
137
|
+
expect(instance.send(:str_to_class, "SyncWhateverWorker")).to eq(false)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -4,11 +4,7 @@ require "rspec"
|
|
4
4
|
require "sqeduler"
|
5
5
|
require "timecop"
|
6
6
|
|
7
|
-
|
8
|
-
:host => "localhost",
|
9
|
-
:db => 1
|
10
|
-
}
|
11
|
-
TEST_REDIS = Redis.new(REDIS_CONFIG)
|
7
|
+
TEST_REDIS = Redis.new(:host => "localhost", :db => 1)
|
12
8
|
|
13
9
|
Timecop.safe_mode = true
|
14
10
|
|
@@ -16,6 +12,7 @@ RSpec.configure do |config|
|
|
16
12
|
config.before(:each) do
|
17
13
|
TEST_REDIS.flushdb
|
18
14
|
Sqeduler::Service.config = nil
|
15
|
+
REDIS_CONFIG = { :host => "localhost", :db => 1 }.clone
|
19
16
|
end
|
20
17
|
config.disable_monkey_patching!
|
21
18
|
end
|
data/sqeduler.gemspec
CHANGED
@@ -27,7 +27,7 @@ Gem::Specification.new do |gem|
|
|
27
27
|
gem.add_development_dependency "pry", "~> 0"
|
28
28
|
gem.add_development_dependency "rake", "~> 10"
|
29
29
|
gem.add_development_dependency "rspec", "~> 3.3"
|
30
|
-
gem.add_development_dependency "rubocop", "~> 0.
|
30
|
+
gem.add_development_dependency "rubocop", "~> 0.36.0"
|
31
31
|
gem.add_development_dependency "timecop", "~> 0"
|
32
32
|
gem.add_development_dependency "yard", "~> 0"
|
33
33
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sqeduler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jared Jenkins
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-01-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sidekiq
|
@@ -114,14 +114,14 @@ dependencies:
|
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version:
|
117
|
+
version: 0.36.0
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version:
|
124
|
+
version: 0.36.0
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: timecop
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -172,6 +172,7 @@ files:
|
|
172
172
|
- Rakefile
|
173
173
|
- lib/sqeduler.rb
|
174
174
|
- lib/sqeduler/config.rb
|
175
|
+
- lib/sqeduler/lock_maintainer.rb
|
175
176
|
- lib/sqeduler/lock_value.rb
|
176
177
|
- lib/sqeduler/middleware/kill_switch.rb
|
177
178
|
- lib/sqeduler/redis_lock.rb
|
@@ -184,10 +185,12 @@ files:
|
|
184
185
|
- lib/sqeduler/worker/kill_switch.rb
|
185
186
|
- lib/sqeduler/worker/synchronization.rb
|
186
187
|
- spec/config_spec.rb
|
188
|
+
- spec/fixtures/empty_schedule.yaml
|
187
189
|
- spec/fixtures/env.rb
|
188
190
|
- spec/fixtures/fake_worker.rb
|
189
191
|
- spec/fixtures/schedule.yaml
|
190
192
|
- spec/integration_spec.rb
|
193
|
+
- spec/lock_maintainer_spec.rb
|
191
194
|
- spec/middleware/kill_switch_spec.rb
|
192
195
|
- spec/service_spec.rb
|
193
196
|
- spec/spec_helper.rb
|
@@ -216,16 +219,18 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
216
219
|
version: '0'
|
217
220
|
requirements: []
|
218
221
|
rubyforge_project:
|
219
|
-
rubygems_version: 2.
|
222
|
+
rubygems_version: 2.4.6
|
220
223
|
signing_key:
|
221
224
|
specification_version: 4
|
222
225
|
summary: Common Sidekiq infrastructure for multi-host applications.
|
223
226
|
test_files:
|
224
227
|
- spec/config_spec.rb
|
228
|
+
- spec/fixtures/empty_schedule.yaml
|
225
229
|
- spec/fixtures/env.rb
|
226
230
|
- spec/fixtures/fake_worker.rb
|
227
231
|
- spec/fixtures/schedule.yaml
|
228
232
|
- spec/integration_spec.rb
|
233
|
+
- spec/lock_maintainer_spec.rb
|
229
234
|
- spec/middleware/kill_switch_spec.rb
|
230
235
|
- spec/service_spec.rb
|
231
236
|
- spec/spec_helper.rb
|