sidekiq_workflows 0.2.1
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/Rakefile +13 -0
- data/lib/sidekiq_workflows.rb +34 -0
- data/lib/sidekiq_workflows/builder.rb +26 -0
- data/lib/sidekiq_workflows/node.rb +16 -0
- data/lib/sidekiq_workflows/root_node.rb +24 -0
- data/lib/sidekiq_workflows/worker.rb +78 -0
- data/lib/sidekiq_workflows/worker_node.rb +38 -0
- metadata +145 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4c14e767d390b989168bde7f4f5ecc2aa1ec385262a61ce658cf31a847468303
|
4
|
+
data.tar.gz: 2f961ee3f477b3b3c1301aaa73abfb62e6209f452416b8ce6a78e0af642e09f0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8888cb766690ac12aa05b37fdfd3eac761619334f8b65e73e6ea8f966c9b660218defd3467d4498f5b10115717c36f031016a6087d554f515d6762b8073e795d
|
7
|
+
data.tar.gz: 7dfd4071261df7b8cea4416592a5791bea584e787dd22c6d4b2d03df24652fc45a0fd3b486afa0be3f2c7df27dad864185e71ba3d264bc27077f94e7a01e4a63
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
require 'rubygems/package_task'
|
3
|
+
|
4
|
+
Rake::TestTask.new do |t|
|
5
|
+
t.libs << 'lib'
|
6
|
+
t.test_files = FileList.new('test/**/*_test.rb')
|
7
|
+
end
|
8
|
+
|
9
|
+
s = Gem::Specification.load("sidekiq_workflows.gemspec")
|
10
|
+
|
11
|
+
Gem::PackageTask.new s do end
|
12
|
+
|
13
|
+
task default: %w[test]
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'sidekiq-pro'
|
3
|
+
|
4
|
+
module SidekiqWorkflows
|
5
|
+
class << self
|
6
|
+
attr_accessor :worker_queue
|
7
|
+
attr_accessor :callback_queue
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'sidekiq_workflows/node'
|
11
|
+
require 'sidekiq_workflows/root_node'
|
12
|
+
require 'sidekiq_workflows/worker_node'
|
13
|
+
require 'sidekiq_workflows/builder'
|
14
|
+
require 'sidekiq_workflows/worker'
|
15
|
+
|
16
|
+
def self.deserialize(string)
|
17
|
+
from_h(JSON.parse(string, symbolize_names: true))
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.from_h(hash, parent = nil)
|
21
|
+
parent ||= hash.key?(:workers) ? WorkerNode.new(workflow_uuid: hash[:workflow_uuid], on_partial_complete: hash[:on_partial_complete], workers: hash[:workers]) : RootNode.new(workflow_uuid: hash[:workflow_uuid], on_partial_complete: hash[:on_partial_complete])
|
22
|
+
hash[:children].each do |h|
|
23
|
+
child = parent.add_group(h[:workers])
|
24
|
+
from_h(h, child)
|
25
|
+
end
|
26
|
+
parent
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.build(workflow_uuid: nil, on_partial_complete: nil, except: [], &block)
|
30
|
+
root = RootNode.new(workflow_uuid: workflow_uuid, on_partial_complete: on_partial_complete)
|
31
|
+
Builder.new(root, except).then(&block)
|
32
|
+
root
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'sidekiq_workflows/node'
|
2
|
+
|
3
|
+
module SidekiqWorkflows
|
4
|
+
class Builder
|
5
|
+
attr_reader :node, :skip_workers
|
6
|
+
|
7
|
+
def initialize(node, skip_workers = [])
|
8
|
+
@node = node
|
9
|
+
@skip_workers = skip_workers
|
10
|
+
end
|
11
|
+
|
12
|
+
def perform(workers, *args, delay: nil)
|
13
|
+
workers = [worker: workers, payload: args, delay: delay] unless workers.is_a?(Array)
|
14
|
+
workers.reject! { |w| skip_workers.include?(w[:worker]) }
|
15
|
+
return self if workers.empty?
|
16
|
+
|
17
|
+
child = @node.add_group(workers)
|
18
|
+
Builder.new(child, skip_workers)
|
19
|
+
end
|
20
|
+
|
21
|
+
def then(&block)
|
22
|
+
instance_eval(&block)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module SidekiqWorkflows
|
2
|
+
module Node
|
3
|
+
def add_group(workers)
|
4
|
+
@children << (child = WorkerNode.new(workers: workers, workflow_uuid: workflow_uuid, on_partial_complete: on_partial_complete, parent: self))
|
5
|
+
child
|
6
|
+
end
|
7
|
+
|
8
|
+
def serialize
|
9
|
+
to_h.to_json
|
10
|
+
end
|
11
|
+
|
12
|
+
def all_nodes
|
13
|
+
[self] + children.flat_map(&:all_nodes)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'sidekiq_workflows/node'
|
2
|
+
|
3
|
+
module SidekiqWorkflows
|
4
|
+
class RootNode
|
5
|
+
include Node
|
6
|
+
|
7
|
+
attr_accessor :workflow_uuid, :on_partial_complete
|
8
|
+
attr_reader :children
|
9
|
+
|
10
|
+
def initialize(workflow_uuid: nil, on_partial_complete: nil)
|
11
|
+
@workflow_uuid = workflow_uuid
|
12
|
+
@on_partial_complete = on_partial_complete
|
13
|
+
@children = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_h
|
17
|
+
{
|
18
|
+
workflow_uuid: workflow_uuid,
|
19
|
+
on_partial_complete: on_partial_complete,
|
20
|
+
children: @children.map(&:to_h)
|
21
|
+
}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'sidekiq_workflows/node'
|
2
|
+
|
3
|
+
module SidekiqWorkflows
|
4
|
+
class Worker
|
5
|
+
include Sidekiq::Worker
|
6
|
+
|
7
|
+
sidekiq_options retry: false
|
8
|
+
|
9
|
+
def perform(workflow)
|
10
|
+
workflow = ensure_deserialized(workflow)
|
11
|
+
|
12
|
+
case workflow.class.name
|
13
|
+
when 'SidekiqWorkflows::RootNode'
|
14
|
+
perform_children(batch, workflow)
|
15
|
+
when 'SidekiqWorkflows::WorkerNode'
|
16
|
+
batch.jobs do
|
17
|
+
child_batch = Sidekiq::Batch.new
|
18
|
+
child_batch.callback_queue = SidekiqWorkflows.callback_queue unless SidekiqWorkflows.callback_queue.nil?
|
19
|
+
child_batch.description = "Workflow #{workflow.workflow_uuid || '-'}"
|
20
|
+
child_batch.on(:complete, 'SidekiqWorkflows::Worker#on_complete', workflow: workflow.serialize, workflow_uuid: workflow.workflow_uuid)
|
21
|
+
child_batch.jobs do
|
22
|
+
workflow.workers.each do |entry|
|
23
|
+
if entry[:delay]
|
24
|
+
entry[:worker].perform_in(entry[:delay], *entry[:payload])
|
25
|
+
else
|
26
|
+
entry[:worker].perform_async(*entry[:payload])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def on_complete(status, options)
|
35
|
+
workflow = ensure_deserialized(options['workflow'])
|
36
|
+
|
37
|
+
if workflow.on_partial_complete
|
38
|
+
klass, method = workflow.on_partial_complete.split('#')
|
39
|
+
ActiveSupport::Inflector.constantize(klass).new.send(method, status, options)
|
40
|
+
end
|
41
|
+
|
42
|
+
perform_children(status.parent_batch, workflow) unless status.failures > 0
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.perform_async(workflow, *args)
|
46
|
+
set(queue: worker_queue).send(:perform_async, workflow.serialize, *args)
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.perform_workflow(workflow, on_complete: nil, on_complete_options: {})
|
50
|
+
batch = Sidekiq::Batch.new
|
51
|
+
batch.callback_queue = SidekiqWorkflows.callback_queue unless SidekiqWorkflows.callback_queue.nil?
|
52
|
+
batch.description = "Workflow #{workflow.workflow_uuid || '-'} root batch"
|
53
|
+
batch.on(:complete, on_complete, on_complete_options.merge(workflow_uuid: workflow.workflow_uuid)) if on_complete
|
54
|
+
batch.jobs do
|
55
|
+
perform_async(workflow)
|
56
|
+
end
|
57
|
+
batch.bid
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def self.worker_queue
|
63
|
+
SidekiqWorkflows.worker_queue || Sidekiq.default_worker_options['queue']
|
64
|
+
end
|
65
|
+
|
66
|
+
def perform_children(batch, workflow)
|
67
|
+
batch.jobs do
|
68
|
+
workflow.children.each do |child|
|
69
|
+
self.class.perform_async(child)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def ensure_deserialized(workflow)
|
75
|
+
workflow.is_a?(String) ? SidekiqWorkflows.deserialize(workflow) : workflow
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'sidekiq_workflows/node'
|
2
|
+
require 'active_support/inflector'
|
3
|
+
|
4
|
+
module SidekiqWorkflows
|
5
|
+
class WorkerNode
|
6
|
+
include Node
|
7
|
+
|
8
|
+
attr_accessor :workers, :workflow_uuid, :on_partial_complete
|
9
|
+
attr_reader :children
|
10
|
+
attr_reader :parent
|
11
|
+
|
12
|
+
def initialize(workers:, workflow_uuid: nil, on_partial_complete: nil, parent: nil)
|
13
|
+
@workers = workers.each do |entry|
|
14
|
+
entry[:worker] = ActiveSupport::Inflector.constantize(entry[:worker]) if entry[:worker].is_a?(String)
|
15
|
+
entry[:delay] = entry[:delay].to_i if entry[:delay]
|
16
|
+
end
|
17
|
+
@workflow_uuid = workflow_uuid
|
18
|
+
@on_partial_complete = on_partial_complete
|
19
|
+
@parent = parent
|
20
|
+
@children = []
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_h
|
24
|
+
{
|
25
|
+
workers: workers.map do |entry|
|
26
|
+
{
|
27
|
+
worker: entry[:worker].name,
|
28
|
+
payload: entry[:payload],
|
29
|
+
delay: entry[:delay]
|
30
|
+
}
|
31
|
+
end,
|
32
|
+
workflow_uuid: workflow_uuid,
|
33
|
+
on_partial_complete: on_partial_complete,
|
34
|
+
children: @children.map(&:to_h)
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
metadata
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sidekiq_workflows
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Marian Theisen
|
8
|
+
- Christian Semmler
|
9
|
+
- Patrick Detlefsen
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2018-08-31 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: sidekiq-pro
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
19
|
+
- - "~>"
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '4.0'
|
22
|
+
- - ">="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 4.0.2
|
25
|
+
type: :runtime
|
26
|
+
prerelease: false
|
27
|
+
version_requirements: !ruby/object:Gem::Requirement
|
28
|
+
requirements:
|
29
|
+
- - "~>"
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: '4.0'
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 4.0.2
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: activesupport
|
37
|
+
requirement: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '5.0'
|
42
|
+
type: :runtime
|
43
|
+
prerelease: false
|
44
|
+
version_requirements: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '5.0'
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: rake
|
51
|
+
requirement: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '12.0'
|
56
|
+
type: :development
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '12.0'
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: mocha
|
65
|
+
requirement: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '1.3'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - "~>"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '1.3'
|
77
|
+
- !ruby/object:Gem::Dependency
|
78
|
+
name: minitest
|
79
|
+
requirement: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - "~>"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '5.0'
|
84
|
+
type: :development
|
85
|
+
prerelease: false
|
86
|
+
version_requirements: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - "~>"
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '5.0'
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: pry
|
93
|
+
requirement: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - "~>"
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: 0.11.3
|
98
|
+
type: :development
|
99
|
+
prerelease: false
|
100
|
+
version_requirements: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - "~>"
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: 0.11.3
|
105
|
+
description: Sidekiq extension providing a workflow API on top of Sidekiq Pro's batches
|
106
|
+
email:
|
107
|
+
- mt@zeit.io
|
108
|
+
- mail@csemmler.com
|
109
|
+
- pd@zeit.io
|
110
|
+
executables: []
|
111
|
+
extensions: []
|
112
|
+
extra_rdoc_files: []
|
113
|
+
files:
|
114
|
+
- Rakefile
|
115
|
+
- lib/sidekiq_workflows.rb
|
116
|
+
- lib/sidekiq_workflows/builder.rb
|
117
|
+
- lib/sidekiq_workflows/node.rb
|
118
|
+
- lib/sidekiq_workflows/root_node.rb
|
119
|
+
- lib/sidekiq_workflows/worker.rb
|
120
|
+
- lib/sidekiq_workflows/worker_node.rb
|
121
|
+
homepage: https://github.com/easymarketing/sidekiq_workflows
|
122
|
+
licenses:
|
123
|
+
- MIT
|
124
|
+
metadata: {}
|
125
|
+
post_install_message:
|
126
|
+
rdoc_options: []
|
127
|
+
require_paths:
|
128
|
+
- lib
|
129
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
requirements: []
|
140
|
+
rubyforge_project:
|
141
|
+
rubygems_version: 2.7.7
|
142
|
+
signing_key:
|
143
|
+
specification_version: 4
|
144
|
+
summary: Sidekiq extension providing a workflow API on top of Sidekiq Pro's batches
|
145
|
+
test_files: []
|