sidekiq-clutch 1.0.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 +7 -0
- data/.gitignore +3 -0
- data/.rspec +3 -0
- data/.rubocop.yml +29 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +163 -0
- data/Rakefile +6 -0
- data/lib/sidekiq/clutch.rb +120 -0
- data/lib/sidekiq/clutch/job_wrapper.rb +32 -0
- data/lib/sidekiq/clutch/jobs_collection.rb +38 -0
- data/lib/sidekiq/clutch/version.rb +5 -0
- data/lib/sidekiq/clutch/worker.rb +24 -0
- data/sidekiq-clutch.gemspec +28 -0
- metadata +129 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ec75202216558f8f183a76de69109178e67ba9bb
|
4
|
+
data.tar.gz: c49621ff95d0667e6d9b2394a1a783a740d240e0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 10eefa778032d53f29c65154057e7ac3f9a7d84c7dfd576da8cc788488f20a744953ea26fedfb2f93812b609b45a382380df77ce901591fc25001c7025219af5
|
7
|
+
data.tar.gz: f1d72de39d77bd3ebc10034620a009bc8982492faf3188917023dbbeead5252fc36d39e62e5d491cdb477f66f48157fd07544016d28d6d357494036d11c41ee9
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
Metrics/LineLength:
|
2
|
+
Max: 120
|
3
|
+
|
4
|
+
Style/ClassAndModuleChildren:
|
5
|
+
Enabled: false
|
6
|
+
|
7
|
+
Style/Documentation:
|
8
|
+
Enabled: false
|
9
|
+
|
10
|
+
Style/FrozenStringLiteralComment:
|
11
|
+
Enabled: false
|
12
|
+
|
13
|
+
Layout/EmptyLineAfterGuardClause:
|
14
|
+
Enabled: false
|
15
|
+
|
16
|
+
Metrics/MethodLength:
|
17
|
+
Enabled: false
|
18
|
+
|
19
|
+
Metrics/AbcSize:
|
20
|
+
Enabled: false
|
21
|
+
|
22
|
+
Metrics/BlockLength:
|
23
|
+
Enabled: false
|
24
|
+
|
25
|
+
Naming/UncommunicativeMethodParamName:
|
26
|
+
Enabled: false
|
27
|
+
|
28
|
+
Style/Next:
|
29
|
+
Enabled: false
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2018 Tim Morgan
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
# Sidekiq::Clutch
|
2
|
+
|
3
|
+
Sidekiq::Clutch is the API I always wanted when working with Sidekiq Pro [Batches](https://github.com/mperham/sidekiq/wiki/Batches). So I built it!
|
4
|
+
|
5
|
+
Features:
|
6
|
+
|
7
|
+
* Add jobs to run in series or parallel or mix-and-match however you wish.
|
8
|
+
* Pass results from one job onto the next job in series.
|
9
|
+
* If running jobs in parallel, pass all the results to the following job in series.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Add this line to your application's Gemfile:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
gem 'sidekiq-clutch'
|
17
|
+
```
|
18
|
+
|
19
|
+
And then execute:
|
20
|
+
|
21
|
+
$ bundle
|
22
|
+
|
23
|
+
Or install it yourself as:
|
24
|
+
|
25
|
+
$ gem install sidekiq-clutch
|
26
|
+
|
27
|
+
## Usage
|
28
|
+
|
29
|
+
Include the `Sidekiq::Clutch::Worker` mixin in your job class and write your `#perform` method as usual. For example:
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
class MyJob1
|
33
|
+
include Sidekiq::Worker
|
34
|
+
include Sidekiq::Clutch::Worker
|
35
|
+
|
36
|
+
def perform
|
37
|
+
# do stuff
|
38
|
+
end
|
39
|
+
end
|
40
|
+
```
|
41
|
+
|
42
|
+
Now, enqueue your jobs using a new `Sidekiq::Clutch` instance, like this:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
clutch = Sidekiq::Clutch.new
|
46
|
+
clutch.jobs << MyJob1
|
47
|
+
clutch.jobs << [MyJob2, 'arg1', 'arg2']
|
48
|
+
clutch.parallel do
|
49
|
+
clutch.jobs << [MyJob3, 3]
|
50
|
+
clutch.jobs << [MyJob3, 4]
|
51
|
+
clutch.jobs << [MyJob3, 5]
|
52
|
+
end
|
53
|
+
clutch.jobs << MyFinalizerJob
|
54
|
+
clutch.engage
|
55
|
+
```
|
56
|
+
|
57
|
+
The jobs will run in this order:
|
58
|
+
|
59
|
+
* First, `MyJob1` will run.
|
60
|
+
* Second, `MyJob2` with args `'arg1'` and `'arg2'` will run.
|
61
|
+
* Third, in parallel, three jobs of `MyJob3`, each with args `3`, `4`, and `5` will run.
|
62
|
+
* Last, the `MyFinalizerJob` will run.
|
63
|
+
|
64
|
+
## Results from Prior Jobs
|
65
|
+
|
66
|
+
You can access the results from the previous job in the series using the `previous_results` method:
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
class MyJob1
|
70
|
+
include Sidekiq::Worker
|
71
|
+
include Sidekiq::Clutch::Worker
|
72
|
+
|
73
|
+
def perform
|
74
|
+
'This string will be passed to the next job in the series'
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
class MyJob2
|
79
|
+
include Sidekiq::Worker
|
80
|
+
include Sidekiq::Clutch::Worker
|
81
|
+
|
82
|
+
def perform(arg1, arg2)
|
83
|
+
puts "results of the previous job (MyJob1):"
|
84
|
+
p previous_results # => ["This string will be passed to the next job in the series"]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
```
|
88
|
+
|
89
|
+
If the previous step in a series was a batch of parallel jobs, then `previous_results` will be an array
|
90
|
+
containing all the results from all the parallel jobs.
|
91
|
+
|
92
|
+
Some notes:
|
93
|
+
- Results are always in an array, even if there was only a single prior job run in series.
|
94
|
+
- Results are serialized as JSON and temporarily stored in Redis, so only return small-ish values.
|
95
|
+
|
96
|
+
## Handling Failure
|
97
|
+
|
98
|
+
When jobs fail, Sidekiq will retry them as usual. See [here](https://github.com/mperham/sidekiq/wiki/Error-Handling) for details on how Sidekiq handles job failure and retries.
|
99
|
+
|
100
|
+
Jobs next in a series will **not** be enqueued by Clutch as long as a prior job is failing.
|
101
|
+
|
102
|
+
If you wish to do something when a job in your batch fails, set `on_failure` like this:
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
clutch = Sidekiq::Clutch.new
|
106
|
+
clutch.on_failure = MyFailureHandlerJob
|
107
|
+
# add jobs here...
|
108
|
+
clutch.engage
|
109
|
+
```
|
110
|
+
|
111
|
+
`MyFailureHandlerJob.new.perform(status)` will be called if one of the following scenarios occur:
|
112
|
+
|
113
|
+
1. A job in series fails.
|
114
|
+
2. One or more jobs in parallel fail and the rest complete.
|
115
|
+
|
116
|
+
Note: retries will continue to occur even after your failure handler job is called.
|
117
|
+
|
118
|
+
## Nested Batches
|
119
|
+
|
120
|
+
You can nest Clutch instances too!
|
121
|
+
|
122
|
+
```ruby
|
123
|
+
class MyNestedJob
|
124
|
+
include Sidekiq::Worker
|
125
|
+
include Sidekiq::Clutch::Worker
|
126
|
+
|
127
|
+
def perform
|
128
|
+
clutch = Sidekiq::Clutch.new(batch)
|
129
|
+
clutch.jobs << [MyJob2, 'arg1', 'arg2']
|
130
|
+
clutch.jobs << [MyJob3, 3]
|
131
|
+
clutch.engage
|
132
|
+
'result from MyNestedJob'
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
clutch = Sidekiq::Clutch.new
|
137
|
+
clutch.jobs << MyJob1
|
138
|
+
clutch.jobs << MyNestedJob
|
139
|
+
clutch.jobs << MyFinalizerJob
|
140
|
+
clutch.engage
|
141
|
+
```
|
142
|
+
|
143
|
+
## Setting the Queue
|
144
|
+
|
145
|
+
You can set the queue for jobs (overriding any queue specified in the job class itself) and callbacks by setting it on Clutch, like this:
|
146
|
+
|
147
|
+
```ruby
|
148
|
+
clutch = Sidekiq::Clutch.new
|
149
|
+
clutch.queue = 'critical'
|
150
|
+
# add jobs here...
|
151
|
+
clutch.engage
|
152
|
+
```
|
153
|
+
|
154
|
+
## Note about the sidekiq-batch gem
|
155
|
+
|
156
|
+
I tested this with the third-party gem [sidekiq-batch](https://github.com/breamware/sidekiq-batch), which
|
157
|
+
purports to be a drop-in replacement for Sidekiq Pro batches. However, that gem seems to not support
|
158
|
+
[nested callbacks](https://github.com/breamware/sidekiq-batch/issues/11#issuecomment-330625800), which my gem
|
159
|
+
relies on. I'm sorry, this gem will **not** work with the sidekiq-batch gem -- it only works with sidekiq-pro.
|
160
|
+
|
161
|
+
## License
|
162
|
+
|
163
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'sidekiq'
|
2
|
+
require 'sidekiq/clutch/version'
|
3
|
+
require 'sidekiq/clutch/worker'
|
4
|
+
require 'sidekiq/clutch/jobs_collection'
|
5
|
+
require 'sidekiq/clutch/job_wrapper'
|
6
|
+
|
7
|
+
module Sidekiq
|
8
|
+
class Clutch
|
9
|
+
def initialize(batch = nil)
|
10
|
+
@batch = batch || Sidekiq::Batch.new
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :batch, :queue
|
14
|
+
|
15
|
+
attr_accessor :current_result_key, :on_failure
|
16
|
+
|
17
|
+
def parallel
|
18
|
+
@parallel = true
|
19
|
+
yield
|
20
|
+
@parallel = false
|
21
|
+
end
|
22
|
+
|
23
|
+
def parallel?
|
24
|
+
@parallel == true
|
25
|
+
end
|
26
|
+
|
27
|
+
def jobs
|
28
|
+
@jobs ||= JobsCollection.new(self)
|
29
|
+
end
|
30
|
+
|
31
|
+
def clear
|
32
|
+
@jobs = nil
|
33
|
+
end
|
34
|
+
|
35
|
+
def queue=(q)
|
36
|
+
@queue = q && q.to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
def engage
|
40
|
+
return if jobs.empty?
|
41
|
+
if batch.mutable?
|
42
|
+
setup_batch
|
43
|
+
else
|
44
|
+
batch.jobs do
|
45
|
+
@batch = Sidekiq::Batch.new
|
46
|
+
setup_batch
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def setup_batch
|
52
|
+
jobs_queue = jobs.raw.dup
|
53
|
+
step = jobs_queue.shift
|
54
|
+
return if step.nil?
|
55
|
+
batch.callback_queue = queue if queue
|
56
|
+
batch.on(:success, Sidekiq::Clutch, 'jobs' => jobs_queue.dup, 'result_key' => step['result_key'])
|
57
|
+
batch.on(:complete, Sidekiq::Clutch, 'on_failure' => on_failure&.name)
|
58
|
+
batch.jobs do
|
59
|
+
if step['series']
|
60
|
+
series_step(step)
|
61
|
+
elsif step['parallel']
|
62
|
+
parallel_step(step)
|
63
|
+
else
|
64
|
+
raise "unknown step: #{step.inspect}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def on_success(status, options)
|
70
|
+
if options['jobs'].empty?
|
71
|
+
clean_up_result_keys(options['result_key'].sub(/-\d+$/, ''))
|
72
|
+
return
|
73
|
+
end
|
74
|
+
parent_batch = Sidekiq::Batch.new(status.parent_bid)
|
75
|
+
service = self.class.new(parent_batch)
|
76
|
+
service.jobs.raw = options['jobs']
|
77
|
+
service.current_result_key = options['result_key']
|
78
|
+
service.engage
|
79
|
+
end
|
80
|
+
|
81
|
+
def on_complete(status, options)
|
82
|
+
return if status.failures.zero?
|
83
|
+
return if options['on_failure'].nil?
|
84
|
+
Object.const_get(options['on_failure']).new.perform(status)
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def series_step(step)
|
90
|
+
(klass, params) = step['series']
|
91
|
+
enqueue_job(klass, params, step['result_key'])
|
92
|
+
end
|
93
|
+
|
94
|
+
def parallel_step(step)
|
95
|
+
step['parallel'].each do |(klass, params)|
|
96
|
+
enqueue_job(klass, params, step['result_key'])
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def enqueue_job(klass, params, result_key)
|
101
|
+
job_options = Object.const_get(klass).sidekiq_options
|
102
|
+
options = {
|
103
|
+
'class' => JobWrapper,
|
104
|
+
'queue' => queue || job_options['queue'],
|
105
|
+
'args' => [batch.bid, klass, params, current_result_key, result_key],
|
106
|
+
'retry' => job_options['retry'],
|
107
|
+
'backtrace' => job_options['backtrace']
|
108
|
+
}
|
109
|
+
Sidekiq::Client.push(options)
|
110
|
+
end
|
111
|
+
|
112
|
+
def clean_up_result_keys(key_base)
|
113
|
+
Sidekiq.redis do |redis|
|
114
|
+
redis.keys(key_base + '*').each do |key|
|
115
|
+
redis.del(key)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Sidekiq
|
2
|
+
class Clutch
|
3
|
+
class JobWrapper
|
4
|
+
include Sidekiq::Worker
|
5
|
+
|
6
|
+
# 22 days - how long a Sidekiq job can live with exponential backoff
|
7
|
+
RESULT_KEY_EXPIRATION_DURATION = 22 * 24 * 60 * 60
|
8
|
+
|
9
|
+
def perform(bid, job_class, args, last_result_key, current_result_key)
|
10
|
+
job = Object.const_get(job_class).new
|
11
|
+
assign_previous_results(job, last_result_key)
|
12
|
+
job.define_singleton_method(:batch) { Sidekiq::Batch.new(bid) }
|
13
|
+
result = job.perform(*args)
|
14
|
+
Sidekiq.redis do |redis|
|
15
|
+
redis.multi do |multi|
|
16
|
+
multi.rpush(current_result_key, result.to_json)
|
17
|
+
multi.expire(current_result_key, RESULT_KEY_EXPIRATION_DURATION)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def assign_previous_results(job, last_result_key)
|
25
|
+
return unless job.respond_to?(:previous_results=)
|
26
|
+
job.previous_results = Sidekiq.redis { |c| c.lrange(last_result_key, 0, -1) }.map do |r|
|
27
|
+
JSON.parse(r, quirks_mode: true) # quirks_mode allows a bare string or number
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Sidekiq
|
2
|
+
class Clutch
|
3
|
+
class JobsCollection
|
4
|
+
def initialize(service)
|
5
|
+
@service = service
|
6
|
+
@jobs = []
|
7
|
+
@result_key_prefix = SecureRandom.uuid
|
8
|
+
@result_key_index = 0
|
9
|
+
end
|
10
|
+
|
11
|
+
def empty?
|
12
|
+
@jobs.empty?
|
13
|
+
end
|
14
|
+
|
15
|
+
def raw
|
16
|
+
@jobs
|
17
|
+
end
|
18
|
+
|
19
|
+
def raw=(jobs)
|
20
|
+
@jobs = jobs
|
21
|
+
end
|
22
|
+
|
23
|
+
def <<((klass, *params))
|
24
|
+
if @service.parallel?
|
25
|
+
@jobs << { 'parallel' => [], 'result_key' => next_result_key } unless @jobs.last && @jobs.last['parallel']
|
26
|
+
@jobs.last['parallel'] << [klass.name, params]
|
27
|
+
else
|
28
|
+
@jobs << { 'series' => [klass.name, params], 'result_key' => next_result_key }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def next_result_key
|
33
|
+
@result_key_index += 1
|
34
|
+
"#{@result_key_prefix}-#{@result_key_index}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Sidekiq
|
2
|
+
class Clutch
|
3
|
+
module Worker
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval do
|
6
|
+
attr_accessor :previous_results
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def perform(last_result_key, current_result_key, args)
|
11
|
+
self.previous_results = Sidekiq.redis { |c| c.lrange(last_result_key, 0, -1) }.map do |r|
|
12
|
+
JSON.parse(r, quirks_mode: true) # quirks_mode allows a bare string or number
|
13
|
+
end
|
14
|
+
result = perform!(*args)
|
15
|
+
Sidekiq.redis do |redis|
|
16
|
+
redis.multi do |multi|
|
17
|
+
multi.rpush(current_result_key, result.to_json)
|
18
|
+
multi.expire(current_result_key, RESULT_KEY_EXPIRATION_DURATION)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'sidekiq/clutch/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'sidekiq-clutch'
|
7
|
+
spec.version = Sidekiq::Clutch::VERSION
|
8
|
+
spec.authors = ['Tim Morgan']
|
9
|
+
spec.email = ['tim@timmorgan.org']
|
10
|
+
|
11
|
+
spec.summary = 'An ergonomic wrapper API for Sidekiq Batches'
|
12
|
+
spec.description = 'Sidekiq::Clutch provides an ergonomic wrapper API for Sidekiq Batches ' \
|
13
|
+
'so you can easily manage serial and parallel jobs.'
|
14
|
+
spec.homepage = 'https://github.com/seven1m/sidekiq-clutch'
|
15
|
+
spec.license = 'MIT'
|
16
|
+
|
17
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
18
|
+
`git ls-files`.split("\n").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
19
|
+
end
|
20
|
+
spec.require_paths = ['lib']
|
21
|
+
|
22
|
+
spec.add_dependency 'sidekiq', '>= 5.0.0'
|
23
|
+
|
24
|
+
spec.add_development_dependency 'pry'
|
25
|
+
spec.add_development_dependency 'bundler', '~> 1.16'
|
26
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
27
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sidekiq-clutch
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tim Morgan
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-11-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: sidekiq
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 5.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 5.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pry
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.16'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.16'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.0'
|
83
|
+
description: Sidekiq::Clutch provides an ergonomic wrapper API for Sidekiq Batches
|
84
|
+
so you can easily manage serial and parallel jobs.
|
85
|
+
email:
|
86
|
+
- tim@timmorgan.org
|
87
|
+
executables: []
|
88
|
+
extensions: []
|
89
|
+
extra_rdoc_files: []
|
90
|
+
files:
|
91
|
+
- ".gitignore"
|
92
|
+
- ".rspec"
|
93
|
+
- ".rubocop.yml"
|
94
|
+
- CHANGELOG.md
|
95
|
+
- Gemfile
|
96
|
+
- LICENSE.txt
|
97
|
+
- README.md
|
98
|
+
- Rakefile
|
99
|
+
- lib/sidekiq/clutch.rb
|
100
|
+
- lib/sidekiq/clutch/job_wrapper.rb
|
101
|
+
- lib/sidekiq/clutch/jobs_collection.rb
|
102
|
+
- lib/sidekiq/clutch/version.rb
|
103
|
+
- lib/sidekiq/clutch/worker.rb
|
104
|
+
- sidekiq-clutch.gemspec
|
105
|
+
homepage: https://github.com/seven1m/sidekiq-clutch
|
106
|
+
licenses:
|
107
|
+
- MIT
|
108
|
+
metadata: {}
|
109
|
+
post_install_message:
|
110
|
+
rdoc_options: []
|
111
|
+
require_paths:
|
112
|
+
- lib
|
113
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
requirements: []
|
124
|
+
rubyforge_project:
|
125
|
+
rubygems_version: 2.5.2.3
|
126
|
+
signing_key:
|
127
|
+
specification_version: 4
|
128
|
+
summary: An ergonomic wrapper API for Sidekiq Batches
|
129
|
+
test_files: []
|