sidekiq-superworker 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +39 -2
- data/app/views/sidekiq/superworker/subjobs.slim +16 -0
- data/lib/sidekiq/superworker.rb +11 -1
- data/lib/sidekiq/superworker/dsl_hash.rb +152 -0
- data/lib/sidekiq/superworker/dsl_parser.rb +16 -49
- data/lib/sidekiq/superworker/subjob_processor.rb +16 -7
- data/lib/sidekiq/superworker/superjob_processor.rb +9 -2
- data/lib/sidekiq/superworker/version.rb +1 -1
- data/lib/sidekiq/superworker/worker.rb +27 -15
- metadata +4 -2
data/README.md
CHANGED
@@ -53,8 +53,6 @@ Superworker.create(:MySuperworker, :user_id, :comment_id) do
|
|
53
53
|
end
|
54
54
|
```
|
55
55
|
|
56
|
-
If you're also using [sidekiq_monitor](https://github.com/socialpandas/sidekiq_monitor), you can easily monitor when a superworker is running and when it has finished.
|
57
|
-
|
58
56
|
Installation
|
59
57
|
------------
|
60
58
|
|
@@ -100,6 +98,45 @@ Superworker.create(:MySuperworker, :user_id, :comment_id) do
|
|
100
98
|
end
|
101
99
|
```
|
102
100
|
|
101
|
+
### Monitoring
|
102
|
+
|
103
|
+
Using [sidekiq_monitor](https://github.com/socialpandas/sidekiq_monitor) with Sidekiq Superworker is strongly encouraged, as it lets you easily monitor when a superjob is running, when it has finished, whether it has encountered errors, and the status of all of its subjobs.
|
104
|
+
|
105
|
+
### Batch Jobs
|
106
|
+
|
107
|
+
By using a `batch` block, you can create batches of subjobs that are all associated with the superjob. The following will run Worker1 and Worker2 in serial for every user ID in the array passed to perform_async.
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
Superworker.create(:MyBatchSuperworker, :user_ids) do
|
111
|
+
batch user_ids: :user_id do
|
112
|
+
Worker1 :user_id
|
113
|
+
Worker2 :user_id
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
MyBatchSuperworker.perform_async([30, 31, 32, 33, 34, 35])
|
118
|
+
```
|
119
|
+
|
120
|
+
Grouping jobs into batches greatly improves your ability to audit them and determine when batches have finished.
|
121
|
+
|
122
|
+
### Superjob Names
|
123
|
+
|
124
|
+
If you're using sidekiq_monitor and want to set a name for a superjob, you can set it in an additional argument, like so:
|
125
|
+
|
126
|
+
```ruby
|
127
|
+
# Unnamed
|
128
|
+
MySuperworker.perform_async(23)
|
129
|
+
|
130
|
+
# Named
|
131
|
+
MySuperworker.perform_async(23, name: 'My job name')
|
132
|
+
```
|
133
|
+
|
134
|
+
### Errors
|
135
|
+
|
136
|
+
If a subjob encounters an exception, the subjobs that depend on it won't run, but the rest of the subjobs will continue as usual.
|
137
|
+
|
138
|
+
If sidekiq_monitor is being used, the exception will be bubbled up to the superjob, which lets you easily see when your superjobs have failed.
|
139
|
+
|
103
140
|
License
|
104
141
|
-------
|
105
142
|
|
@@ -0,0 +1,16 @@
|
|
1
|
+
- subjobs = Sidekiq::Superworker::Subjob.where(superjob_id: job.jid).where('subworker_class != ?', 'batch').order('subjob_id')
|
2
|
+
|
3
|
+
table.table.table-condensed.table-striped.table-hover
|
4
|
+
tr
|
5
|
+
th ID
|
6
|
+
th Class
|
7
|
+
th Args
|
8
|
+
th Status
|
9
|
+
th JID
|
10
|
+
- subjobs.each do |subjob|
|
11
|
+
tr
|
12
|
+
td = subjob.id
|
13
|
+
td = subjob.subworker_class
|
14
|
+
td = subjob.arg_values
|
15
|
+
td = subjob.status
|
16
|
+
td = subjob.jid
|
data/lib/sidekiq/superworker.rb
CHANGED
@@ -28,4 +28,14 @@ Sidekiq.configure_server do |config|
|
|
28
28
|
end
|
29
29
|
|
30
30
|
Superworker = Sidekiq::Superworker::Worker unless Object.const_defined?('Superworker')
|
31
|
-
|
31
|
+
|
32
|
+
# If sidekiq_monitor is being used, customize how superjobs are monitored
|
33
|
+
if defined?(Sidekiq::Monitor)
|
34
|
+
# Make Cleaner ignore superjobs, as they don't exist in Redis and thus won't be synced with Sidekiq::Monitor::Job
|
35
|
+
Sidekiq::Monitor::Cleaner.add_ignored_queue(Sidekiq::Superworker::SuperjobProcessor.queue_name) if defined?(Sidekiq::Monitor)
|
36
|
+
|
37
|
+
# Add a custom view that shows the subjobs for a superjob
|
38
|
+
Sidekiq::Monitor::CustomViews.add 'Subjobs', "#{directory}/../../app/views/sidekiq/superworker/subjobs" do |job|
|
39
|
+
job.queue == Sidekiq::Superworker::SuperjobProcessor.queue_name.to_s
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
module Sidekiq
|
2
|
+
module Superworker
|
3
|
+
class DSLHash
|
4
|
+
attr_accessor :record_id, :records
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
reset
|
8
|
+
end
|
9
|
+
|
10
|
+
def nested_hash_to_records(nested_hash, args)
|
11
|
+
reset
|
12
|
+
@args = args
|
13
|
+
nested_hash_to_records_recursive(nested_hash)
|
14
|
+
end
|
15
|
+
|
16
|
+
def rewrite_ids_of_nested_hash(nested_hash, record_id)
|
17
|
+
reset
|
18
|
+
@record_id = record_id
|
19
|
+
rewrite_ids_of_nested_hash_recursive(nested_hash)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def reset
|
25
|
+
@args = {}
|
26
|
+
@records = {}
|
27
|
+
@record_id = 1
|
28
|
+
end
|
29
|
+
|
30
|
+
def nested_hash_to_records_recursive(nested_hash, options={})
|
31
|
+
return @records if nested_hash.blank?
|
32
|
+
|
33
|
+
defaults = {
|
34
|
+
parent_id: nil,
|
35
|
+
scoped_args: nil # Args that are scoped to this subset of the nested hash (necessary for batch hashes)
|
36
|
+
}
|
37
|
+
options.reverse_merge!(defaults)
|
38
|
+
parent_id = options[:parent_id]
|
39
|
+
last_id = nil
|
40
|
+
|
41
|
+
nested_hash.values.each do |value|
|
42
|
+
id = @record_id
|
43
|
+
@record_id += 1
|
44
|
+
arg_values = value[:arg_keys].collect do |arg_key|
|
45
|
+
# Allow for subjob arg_values to be set within the superworker definition; if a symbol is
|
46
|
+
# used in the DSL, use @args[arg_key], and otherwise use arg_key as the value
|
47
|
+
if arg_key.is_a?(Symbol)
|
48
|
+
options[:scoped_args] ? options[:scoped_args][arg_key] : @args[arg_key]
|
49
|
+
else
|
50
|
+
arg_key
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
@records[id] = {
|
55
|
+
subjob_id: id,
|
56
|
+
subworker_class: value[:subworker_class].to_s,
|
57
|
+
arg_keys: value[:arg_keys],
|
58
|
+
arg_values: arg_values,
|
59
|
+
parent_id: parent_id
|
60
|
+
}
|
61
|
+
if value[:subworker_class] == :batch
|
62
|
+
@records[id][:children_ids] = children_ids_for_batch(value[:children], arg_values[0])
|
63
|
+
end
|
64
|
+
|
65
|
+
@records[last_id][:next_id] = id if @records[last_id]
|
66
|
+
last_id = id
|
67
|
+
|
68
|
+
if parent_id && @records[parent_id]
|
69
|
+
@records[parent_id][:children_ids] ||= []
|
70
|
+
@records[parent_id][:children_ids] << id
|
71
|
+
end
|
72
|
+
|
73
|
+
nested_hash_to_records_recursive(value[:children], parent_id: id, scoped_args: options[:scoped_args]) if value[:children] && value[:subworker_class] != :batch
|
74
|
+
end
|
75
|
+
@records
|
76
|
+
end
|
77
|
+
|
78
|
+
def rewrite_ids_of_nested_hash_recursive(nested_hash)
|
79
|
+
new_hash = {}
|
80
|
+
nested_hash.each do |old_record_id, record|
|
81
|
+
@record_id += 1
|
82
|
+
parent_record_id = @record_id
|
83
|
+
new_hash[parent_record_id] = record
|
84
|
+
if record[:children]
|
85
|
+
new_hash[parent_record_id][:children] = rewrite_ids_of_nested_hash_recursive(record[:children])
|
86
|
+
end
|
87
|
+
end
|
88
|
+
new_hash
|
89
|
+
end
|
90
|
+
|
91
|
+
def children_ids_for_batch(subjobs, batch_keys_to_iteration_keys)
|
92
|
+
iteration_keys = batch_keys_to_iteration_keys.values
|
93
|
+
batch_iteration_arg_value_arrays = get_batch_iteration_arg_value_arrays(batch_keys_to_iteration_keys)
|
94
|
+
|
95
|
+
batch_id = @record_id - 1
|
96
|
+
|
97
|
+
children_ids = []
|
98
|
+
batch_iteration_arg_value_arrays.each do |batch_iteration_arg_value_array|
|
99
|
+
iteration_args = {}
|
100
|
+
batch_iteration_arg_value_array.each_with_index do |arg_value, arg_index|
|
101
|
+
arg_key = iteration_keys[arg_index]
|
102
|
+
iteration_args[arg_key] = arg_value
|
103
|
+
end
|
104
|
+
|
105
|
+
batch_child_id = @record_id
|
106
|
+
batch_child = {
|
107
|
+
subjob_id: batch_child_id,
|
108
|
+
subworker_class: 'batch_child',
|
109
|
+
arg_keys: iteration_keys,
|
110
|
+
arg_values: iteration_args.values,
|
111
|
+
parent_id: batch_id
|
112
|
+
}
|
113
|
+
@records[batch_child_id] = batch_child
|
114
|
+
|
115
|
+
@record_id += 1
|
116
|
+
subjobs.values.each_with_index do |subjob, index|
|
117
|
+
subjob_id = @record_id
|
118
|
+
@record_id += 1
|
119
|
+
subjob = subjob.dup
|
120
|
+
children = subjob.delete(:children)
|
121
|
+
subjob[:subjob_id] = subjob_id
|
122
|
+
subjob[:parent_id] = batch_child_id
|
123
|
+
subjob[:arg_values] = iteration_args.values
|
124
|
+
@records[subjob_id] = subjob
|
125
|
+
nested_hash_to_records_recursive(children, parent_id: subjob_id, scoped_args: iteration_args)
|
126
|
+
subjob[:next_id] = subjob_id + 1 if index < (subjobs.values.length - 1)
|
127
|
+
end
|
128
|
+
|
129
|
+
children_ids << batch_child_id
|
130
|
+
end
|
131
|
+
|
132
|
+
children_ids
|
133
|
+
end
|
134
|
+
|
135
|
+
# Returns an array of argument value arrays, each of which should be passed to each of the
|
136
|
+
# batch iterations
|
137
|
+
def get_batch_iteration_arg_value_arrays(batch_keys_to_iteration_keys)
|
138
|
+
batch_keys = batch_keys_to_iteration_keys.keys
|
139
|
+
batch_keys_to_batch_values = @args.slice(*(batch_keys))
|
140
|
+
|
141
|
+
batch_values = batch_keys_to_batch_values.values
|
142
|
+
first_batch_value = batch_values.pop
|
143
|
+
if batch_values.length > 0
|
144
|
+
batch_values = first_batch_value.zip(batch_values)
|
145
|
+
else
|
146
|
+
batch_values = first_batch_value.zip
|
147
|
+
end
|
148
|
+
batch_values
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
@@ -3,75 +3,42 @@ module Sidekiq
|
|
3
3
|
class DSLParser
|
4
4
|
def self.parse(block)
|
5
5
|
@dsl_evaluator = DSLEvaluator.new
|
6
|
-
|
7
|
-
{
|
8
|
-
records: @records,
|
9
|
-
nested_records: @nested_records
|
10
|
-
}
|
11
|
-
end
|
12
|
-
|
13
|
-
def self.set_records_from_block(block)
|
6
|
+
@dsl_hash = DSLHash.new
|
14
7
|
@record_id = 0
|
15
|
-
|
16
|
-
@nested_records = block_to_nested_records(block)
|
17
|
-
set_records_from_nested_records(@nested_records)
|
18
|
-
end
|
19
|
-
|
20
|
-
def self.set_records_from_nested_records(nested_records, parent_id=nil)
|
21
|
-
last_id = nil
|
22
|
-
nested_records.each do |id, value|
|
23
|
-
@records[id] = {
|
24
|
-
subjob_id: id,
|
25
|
-
subworker_class: value[:subworker_class].to_s,
|
26
|
-
arg_keys: value[:arg_keys],
|
27
|
-
parent_id: parent_id,
|
28
|
-
children_ids: value[:children] ? value[:children].keys : nil
|
29
|
-
}
|
30
|
-
@records[last_id][:next_id] = id if @records[last_id]
|
31
|
-
last_id = id
|
32
|
-
set_records_from_nested_records(value[:children], id) if value[:children]
|
33
|
-
end
|
8
|
+
block_to_nested_hash(block)
|
34
9
|
end
|
35
10
|
|
36
|
-
def self.
|
11
|
+
def self.block_to_nested_hash(block)
|
37
12
|
fiber = Fiber.new do
|
38
13
|
@dsl_evaluator.instance_eval(&block)
|
39
14
|
end
|
40
15
|
|
41
|
-
|
16
|
+
nested_hash = {}
|
42
17
|
while (method_result = fiber.resume)
|
43
|
-
method,
|
18
|
+
method, args, block = method_result
|
44
19
|
@record_id += 1
|
45
20
|
if block
|
46
|
-
|
21
|
+
if method == :batch
|
22
|
+
nested_hash[@record_id] = { subworker_class: method, arg_keys: args, children: block_to_nested_hash(block) }
|
23
|
+
else
|
24
|
+
nested_hash[@record_id] = { subworker_class: method, arg_keys: args, children: block_to_nested_hash(block) }
|
25
|
+
end
|
47
26
|
else
|
48
|
-
|
27
|
+
nested_hash[@record_id] = { subworker_class: method, arg_keys: args }
|
49
28
|
end
|
50
29
|
|
51
|
-
# For superworkers nested within other superworkers, we'll take the subworkers'
|
30
|
+
# For superworkers nested within other superworkers, we'll take the subworkers' nested_hash,
|
52
31
|
# adjust their ids to fit in with our current @record_id value, and add them into the tree.
|
53
|
-
|
32
|
+
unless [:parallel, :batch].include?(method)
|
54
33
|
subworker_class = method.to_s.constantize
|
55
34
|
if subworker_class.respond_to?(:is_a_superworker?) && subworker_class.is_a_superworker?
|
56
35
|
parent_record_id = @record_id
|
57
|
-
|
36
|
+
nested_hash[parent_record_id][:children] = @dsl_hash.rewrite_ids_of_nested_hash(subworker_class.nested_hash, @record_id)
|
37
|
+
@record_id = @dsl_hash.record_id
|
58
38
|
end
|
59
39
|
end
|
60
40
|
end
|
61
|
-
|
62
|
-
end
|
63
|
-
|
64
|
-
def self.rewrite_ids_of_subworker_records(nested_records)
|
65
|
-
new_hash = {}
|
66
|
-
nested_records.each do |old_record_id, record|
|
67
|
-
@record_id += 1
|
68
|
-
parent_record_id = @record_id
|
69
|
-
new_hash[parent_record_id] = record
|
70
|
-
if record[:children]
|
71
|
-
new_hash[parent_record_id][:children] = rewrite_ids_of_subworker_records(record[:children])
|
72
|
-
end
|
73
|
-
end
|
74
|
-
new_hash
|
41
|
+
nested_hash
|
75
42
|
end
|
76
43
|
end
|
77
44
|
end
|
@@ -16,6 +16,15 @@ module Sidekiq
|
|
16
16
|
enqueue(child)
|
17
17
|
end
|
18
18
|
jid = jids.first
|
19
|
+
elsif subjob.subworker_class == 'batch'
|
20
|
+
subjob.update_attribute(:status, 'running')
|
21
|
+
|
22
|
+
Superworker.debug "#{subjob.to_info}: Enqueueing batch children"
|
23
|
+
jids = subjob.children.collect do |child|
|
24
|
+
child.update_attribute(:status, 'running')
|
25
|
+
enqueue(child.children.first)
|
26
|
+
end
|
27
|
+
jid = jids.first
|
19
28
|
else
|
20
29
|
klass = "::#{subjob.subworker_class}".constantize
|
21
30
|
|
@@ -77,11 +86,14 @@ module Sidekiq
|
|
77
86
|
Superworker.debug "#{subjob.to_info}: Descendants are complete"
|
78
87
|
subjob.update_attribute(:descendants_are_complete, true)
|
79
88
|
|
89
|
+
if subjob.subworker_class == 'batch_child' || subjob.subworker_class == 'batch'
|
90
|
+
complete(subjob)
|
91
|
+
end
|
92
|
+
|
80
93
|
parent = subjob.parent
|
81
94
|
is_child_of_parallel = parent && parent.subworker_class == 'parallel'
|
82
95
|
|
83
|
-
# If
|
84
|
-
# and call descendants_are_complete(parent) if so
|
96
|
+
# If a parent exists, check whether this subjob's siblings are all complete
|
85
97
|
if parent
|
86
98
|
siblings_descendants_are_complete = parent.children.all? { |child| child.descendants_are_complete }
|
87
99
|
if siblings_descendants_are_complete
|
@@ -99,11 +111,8 @@ module Sidekiq
|
|
99
111
|
return
|
100
112
|
end
|
101
113
|
|
102
|
-
#
|
103
|
-
|
104
|
-
descendants_are_complete(parent)
|
105
|
-
# Otherwise, this is the final subjob of the superjob
|
106
|
-
else
|
114
|
+
# If there isn't a parent, then, this is the final subjob of the superjob
|
115
|
+
unless parent
|
107
116
|
Superworker.debug "#{subjob.to_info}: Superjob is complete"
|
108
117
|
SuperjobProcessor.complete(subjob.superjob_id)
|
109
118
|
end
|
@@ -5,7 +5,9 @@ module Sidekiq
|
|
5
5
|
:superworker
|
6
6
|
end
|
7
7
|
|
8
|
-
def self.create(superjob_id, superworker_class_name, args, subjobs)
|
8
|
+
def self.create(superjob_id, superworker_class_name, args, subjobs, options={})
|
9
|
+
Superworker.debug "Superworker ##{superjob_id}: create"
|
10
|
+
|
9
11
|
# If sidekiq_monitor is being used, create a Sidekiq::Monitor::Job for the superjob
|
10
12
|
if defined?(Sidekiq::Monitor)
|
11
13
|
now = Time.now
|
@@ -16,7 +18,8 @@ module Sidekiq
|
|
16
18
|
args: args,
|
17
19
|
enqueued_at: now,
|
18
20
|
started_at: now,
|
19
|
-
status: 'running'
|
21
|
+
status: 'running',
|
22
|
+
name: options[:name]
|
20
23
|
)
|
21
24
|
end
|
22
25
|
|
@@ -26,6 +29,8 @@ module Sidekiq
|
|
26
29
|
end
|
27
30
|
|
28
31
|
def self.complete(superjob_id)
|
32
|
+
Superworker.debug "Superworker ##{superjob_id}: complete"
|
33
|
+
|
29
34
|
# Set the superjob Sidekiq::Monitor::Job as being complete
|
30
35
|
if defined?(Sidekiq::Monitor)
|
31
36
|
job = Sidekiq::Monitor::Job.where(queue: queue_name, jid: superjob_id).first
|
@@ -39,6 +44,8 @@ module Sidekiq
|
|
39
44
|
end
|
40
45
|
|
41
46
|
def self.error(superjob_id, worker, item, exception)
|
47
|
+
Superworker.debug "Superworker ##{superjob_id}: error"
|
48
|
+
|
42
49
|
if defined?(Sidekiq::Monitor)
|
43
50
|
job = Sidekiq::Monitor::Job.where(queue: queue_name, jid: superjob_id).first
|
44
51
|
if job
|
@@ -3,44 +3,56 @@ module Sidekiq
|
|
3
3
|
class Worker
|
4
4
|
def self.create(*args, &block)
|
5
5
|
class_name = args.shift.to_sym
|
6
|
-
|
7
|
-
create_class(class_name, args,
|
6
|
+
nested_hash = DSLParser.parse(block)
|
7
|
+
create_class(class_name, args, nested_hash)
|
8
8
|
end
|
9
9
|
|
10
10
|
protected
|
11
11
|
|
12
|
-
def self.create_class(class_name, arg_keys,
|
12
|
+
def self.create_class(class_name, arg_keys, nested_hash)
|
13
13
|
klass = Class.new do
|
14
14
|
@class_name = class_name
|
15
15
|
@arg_keys = arg_keys
|
16
|
-
@
|
17
|
-
@
|
16
|
+
@nested_hash = nested_hash
|
17
|
+
@dsl_hash = DSLHash.new
|
18
18
|
|
19
19
|
class << self
|
20
|
-
attr_reader :
|
20
|
+
attr_reader :nested_hash
|
21
21
|
|
22
22
|
def is_a_superworker?
|
23
23
|
true
|
24
24
|
end
|
25
25
|
|
26
26
|
def perform_async(*arg_values)
|
27
|
+
superjob_options = {}
|
28
|
+
|
29
|
+
# If an additional argument value is given, it's the superjob's options
|
30
|
+
if (arg_values.length == @arg_keys.length + 1) && arg_values.last.is_a?(Hash)
|
31
|
+
superjob_options = arg_values.last
|
32
|
+
elsif @arg_keys.length != arg_values.length
|
33
|
+
raise "Wrong number of arguments for #{name}.perform_async (#{arg_values.length} for #{@arg_keys.length})"
|
34
|
+
end
|
35
|
+
|
27
36
|
@args = Hash[@arg_keys.zip(arg_values)]
|
28
|
-
|
29
|
-
|
37
|
+
@superjob_id = SecureRandom.hex(12)
|
38
|
+
subjobs = create_subjobs(arg_values)
|
39
|
+
SuperjobProcessor.create(@superjob_id, @class_name, arg_values, subjobs, superjob_options)
|
30
40
|
end
|
31
41
|
|
32
42
|
protected
|
33
43
|
|
34
|
-
def create_subjobs
|
35
|
-
|
36
|
-
|
44
|
+
def create_subjobs(arg_values)
|
45
|
+
records = @dsl_hash.nested_hash_to_records(@nested_hash, @args)
|
46
|
+
records.collect do |id, record|
|
37
47
|
record[:status] = 'initialized'
|
38
48
|
record[:superjob_id] = @superjob_id
|
39
49
|
record[:superworker_class] = @class_name
|
40
|
-
record
|
41
|
-
|
42
|
-
|
43
|
-
|
50
|
+
unless record.key?(:arg_values)
|
51
|
+
record[:arg_values] = record[:arg_keys].collect do |arg_key|
|
52
|
+
# Allow for subjob arg_values to be set within the superworker definition; if a symbol is
|
53
|
+
# used in the DSL, use @args[arg_key], and otherwise use arg_key as the value
|
54
|
+
arg_key.is_a?(Symbol) ? @args[arg_key] : arg_key
|
55
|
+
end
|
44
56
|
end
|
45
57
|
Sidekiq::Superworker::Subjob.create(record)
|
46
58
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sidekiq-superworker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-07-
|
12
|
+
date: 2013-07-10 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: sidekiq
|
@@ -99,9 +99,11 @@ extensions: []
|
|
99
99
|
extra_rdoc_files: []
|
100
100
|
files:
|
101
101
|
- app/models/sidekiq/superworker/subjob.rb
|
102
|
+
- app/views/sidekiq/superworker/subjobs.slim
|
102
103
|
- lib/generators/sidekiq/superworker/install/install_generator.rb
|
103
104
|
- lib/generators/sidekiq/superworker/install/templates/create_sidekiq_superworker_subjobs.rb
|
104
105
|
- lib/sidekiq/superworker/dsl_evaluator.rb
|
106
|
+
- lib/sidekiq/superworker/dsl_hash.rb
|
105
107
|
- lib/sidekiq/superworker/dsl_parser.rb
|
106
108
|
- lib/sidekiq/superworker/logging.rb
|
107
109
|
- lib/sidekiq/superworker/processor.rb
|