nxt_pipeline 0.2.8 → 0.4.2
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 +4 -4
- data/.circleci/config.yml +5 -1
- data/.pryrc +6 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +8 -2
- data/Gemfile.lock +32 -26
- data/README.md +41 -26
- data/lib/nxt_pipeline.rb +1 -0
- data/lib/nxt_pipeline/constructor.rb +20 -0
- data/lib/nxt_pipeline/error_callback.rb +2 -2
- data/lib/nxt_pipeline/pipeline.rb +52 -33
- data/lib/nxt_pipeline/step.rb +47 -22
- data/lib/nxt_pipeline/version.rb +2 -1
- data/nxt_pipeline.gemspec +3 -3
- metadata +10 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0ddc6f3289300268adabdfda7f6b0a2c50561e9127f6951f0a29ebfb26d48298
|
|
4
|
+
data.tar.gz: 13af4e35b2014025fb33d16bd9ed1cf74048d6e20404035c5001fedf7db18b02
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c174e7fae2b76cb47b0b2bd1388ad50796603d49283c94056e5af96fbbf46d5d51c745c2cf09015967ac5aa92057f94ec3e6b86412e93686b6b1728db4058c7a
|
|
7
|
+
data.tar.gz: b9e44023b319bd809e71b83eae038676f51e06aae032c40686ed9c1eee6ee9093b7fe38814c22db9139cf4e2ba5d2bfefeda258d70fb883a7a3e738e27429f46
|
data/.circleci/config.yml
CHANGED
|
@@ -7,7 +7,9 @@ jobs:
|
|
|
7
7
|
build:
|
|
8
8
|
docker:
|
|
9
9
|
# specify the version you desire here
|
|
10
|
-
- image: circleci/ruby:2.
|
|
10
|
+
- image: circleci/ruby:2.7.0-node
|
|
11
|
+
environment:
|
|
12
|
+
BUNDLER_VERSION: 2.1.4
|
|
11
13
|
|
|
12
14
|
working_directory: ~/repo
|
|
13
15
|
|
|
@@ -19,6 +21,8 @@ jobs:
|
|
|
19
21
|
keys:
|
|
20
22
|
- v1-dependencies-{{ checksum "Gemfile.lock" }}
|
|
21
23
|
|
|
24
|
+
- run: gem install bundler --version $BUNDLER_VERSION
|
|
25
|
+
|
|
22
26
|
- run:
|
|
23
27
|
name: install dependencies
|
|
24
28
|
command: |
|
data/.pryrc
ADDED
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.
|
|
1
|
+
2.7.0
|
data/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
##
|
|
1
|
+
## nxt_pipeline 0.4.2 (October 12, 2020)
|
|
2
|
+
|
|
3
|
+
* Fix bug when registering an error without passing arguments in which case the callback didn't get executed. More info: https://github.com/nxt-insurance/nxt_pipeline/issues/39
|
|
4
|
+
|
|
5
|
+
## nxt_pipeline 0.4.1 (March 13, 2020)
|
|
6
|
+
|
|
7
|
+
* Fix deprecation warnings for Ruby 2.7
|
|
2
8
|
|
|
3
9
|
## nxt_pipeline 0.2.0 (March 10, 2019)
|
|
4
10
|
|
|
@@ -14,7 +20,7 @@
|
|
|
14
20
|
Renamed `NxtPipeline::Pipeline#burst?` to `NxtPipeline::Pipeline#failed?`.
|
|
15
21
|
Renamed `NxtPipeline::Pipeline#burst_segment` to `NxtPipeline::Pipeline#failed_step`.
|
|
16
22
|
Renamed `NxtPipeline::Pipeline::rescue_segment_burst` to `NxtPipeline::Pipeline::rescue_errors`.
|
|
17
|
-
|
|
23
|
+
|
|
18
24
|
*Nils Sommer*
|
|
19
25
|
|
|
20
26
|
* Setup [guard](https://github.com/guard/guard) to run specs upon file changes during development.
|
data/Gemfile.lock
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
nxt_pipeline (0.2
|
|
4
|
+
nxt_pipeline (0.4.2)
|
|
5
5
|
activesupport
|
|
6
6
|
|
|
7
7
|
GEM
|
|
8
8
|
remote: https://rubygems.org/
|
|
9
9
|
specs:
|
|
10
|
-
activesupport (
|
|
10
|
+
activesupport (6.0.3.4)
|
|
11
11
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
12
12
|
i18n (>= 0.7, < 2)
|
|
13
13
|
minitest (~> 5.1)
|
|
14
14
|
tzinfo (~> 1.1)
|
|
15
|
+
zeitwerk (~> 2.2, >= 2.2.2)
|
|
16
|
+
byebug (11.1.1)
|
|
15
17
|
coderay (1.1.2)
|
|
16
|
-
concurrent-ruby (1.1.
|
|
18
|
+
concurrent-ruby (1.1.7)
|
|
17
19
|
diff-lcs (1.3)
|
|
18
20
|
ffi (1.11.1)
|
|
19
21
|
formatador (0.2.5)
|
|
@@ -31,59 +33,63 @@ GEM
|
|
|
31
33
|
guard (~> 2.1)
|
|
32
34
|
guard-compat (~> 1.1)
|
|
33
35
|
rspec (>= 2.99.0, < 4.0)
|
|
34
|
-
i18n (1.
|
|
36
|
+
i18n (1.8.5)
|
|
35
37
|
concurrent-ruby (~> 1.0)
|
|
36
38
|
listen (3.1.5)
|
|
37
39
|
rb-fsevent (~> 0.9, >= 0.9.4)
|
|
38
40
|
rb-inotify (~> 0.9, >= 0.9.7)
|
|
39
41
|
ruby_dep (~> 1.2)
|
|
40
42
|
lumberjack (1.0.13)
|
|
41
|
-
method_source (0.
|
|
42
|
-
minitest (5.
|
|
43
|
+
method_source (1.0.0)
|
|
44
|
+
minitest (5.14.2)
|
|
43
45
|
nenv (0.3.0)
|
|
44
46
|
notiffany (0.1.1)
|
|
45
47
|
nenv (~> 0.1)
|
|
46
48
|
shellany (~> 0.0)
|
|
47
|
-
pry (0.
|
|
48
|
-
coderay (~> 1.1
|
|
49
|
-
method_source (~>
|
|
50
|
-
|
|
49
|
+
pry (0.13.0)
|
|
50
|
+
coderay (~> 1.1)
|
|
51
|
+
method_source (~> 1.0)
|
|
52
|
+
pry-byebug (3.9.0)
|
|
53
|
+
byebug (~> 11.0)
|
|
54
|
+
pry (~> 0.13.0)
|
|
55
|
+
rake (13.0.1)
|
|
51
56
|
rb-fsevent (0.10.3)
|
|
52
57
|
rb-inotify (0.10.0)
|
|
53
58
|
ffi (~> 1.0)
|
|
54
|
-
rspec (3.
|
|
55
|
-
rspec-core (~> 3.
|
|
56
|
-
rspec-expectations (~> 3.
|
|
57
|
-
rspec-mocks (~> 3.
|
|
58
|
-
rspec-core (3.
|
|
59
|
-
rspec-support (~> 3.
|
|
60
|
-
rspec-expectations (3.
|
|
59
|
+
rspec (3.9.0)
|
|
60
|
+
rspec-core (~> 3.9.0)
|
|
61
|
+
rspec-expectations (~> 3.9.0)
|
|
62
|
+
rspec-mocks (~> 3.9.0)
|
|
63
|
+
rspec-core (3.9.0)
|
|
64
|
+
rspec-support (~> 3.9.0)
|
|
65
|
+
rspec-expectations (3.9.0)
|
|
61
66
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
62
|
-
rspec-support (~> 3.
|
|
63
|
-
rspec-mocks (3.
|
|
67
|
+
rspec-support (~> 3.9.0)
|
|
68
|
+
rspec-mocks (3.9.0)
|
|
64
69
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
65
|
-
rspec-support (~> 3.
|
|
66
|
-
rspec-support (3.
|
|
70
|
+
rspec-support (~> 3.9.0)
|
|
71
|
+
rspec-support (3.9.0)
|
|
67
72
|
rspec_junit_formatter (0.4.1)
|
|
68
73
|
rspec-core (>= 2, < 4, != 2.12.0)
|
|
69
74
|
ruby_dep (1.5.0)
|
|
70
75
|
shellany (0.0.1)
|
|
71
76
|
thor (0.20.3)
|
|
72
77
|
thread_safe (0.3.6)
|
|
73
|
-
tzinfo (1.2.
|
|
78
|
+
tzinfo (1.2.7)
|
|
74
79
|
thread_safe (~> 0.1)
|
|
80
|
+
zeitwerk (2.4.0)
|
|
75
81
|
|
|
76
82
|
PLATFORMS
|
|
77
83
|
ruby
|
|
78
84
|
|
|
79
85
|
DEPENDENCIES
|
|
80
|
-
bundler (~> 1
|
|
86
|
+
bundler (~> 2.1)
|
|
81
87
|
guard-rspec
|
|
82
88
|
nxt_pipeline!
|
|
83
|
-
pry
|
|
84
|
-
rake (~>
|
|
89
|
+
pry-byebug
|
|
90
|
+
rake (~> 13.0)
|
|
85
91
|
rspec (~> 3.0)
|
|
86
92
|
rspec_junit_formatter
|
|
87
93
|
|
|
88
94
|
BUNDLED WITH
|
|
89
|
-
1.
|
|
95
|
+
2.1.4
|
data/README.md
CHANGED
|
@@ -32,26 +32,31 @@ by the step yielded to the constructor.
|
|
|
32
32
|
```ruby
|
|
33
33
|
pipeline = NxtPipeline::Pipeline.new do |p|
|
|
34
34
|
# Add a named constructor that will be used to execute your steps later
|
|
35
|
-
# All options that you pass in your step will be available through accessors in your constructor
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
# All options that you pass in your step will be available through accessors in your constructor
|
|
36
|
+
# You can call :to_s on a step to set it by default. You can later overwrite at execution for each step if needed.
|
|
37
|
+
p.constructor(:service, default: true) do |step, arg:|
|
|
38
|
+
step.to_s = step.service_class.to_s
|
|
39
|
+
result = step.service_class.new(options: arg).call
|
|
40
|
+
result && { arg: result }
|
|
38
41
|
end
|
|
39
42
|
|
|
40
|
-
p.constructor(:job) do |step, arg
|
|
41
|
-
step.job_class.perform_later(*arg) && arg
|
|
43
|
+
p.constructor(:job) do |step, arg:|
|
|
44
|
+
step.job_class.perform_later(*arg) && { arg: arg }
|
|
42
45
|
end
|
|
43
46
|
end
|
|
44
47
|
|
|
45
48
|
# Once a pipeline was created you can still configure it
|
|
46
|
-
pipeline.constructor(:call) do |step, arg
|
|
47
|
-
step.caller.new(arg).call
|
|
49
|
+
pipeline.constructor(:call) do |step, arg:|
|
|
50
|
+
result = step.caller.new(arg).call
|
|
51
|
+
result && { arg: result }
|
|
48
52
|
end
|
|
49
53
|
|
|
50
54
|
# same with block syntax
|
|
51
55
|
# You can use this to split up execution from configuration
|
|
52
56
|
pipeline.configure do |p|
|
|
53
|
-
p.constructor(:call) do |step, arg
|
|
54
|
-
step.caller.new(arg).call
|
|
57
|
+
p.constructor(:call) do |step, arg:|
|
|
58
|
+
result = step.caller.new(arg).call
|
|
59
|
+
result && { arg: result }
|
|
55
60
|
end
|
|
56
61
|
end
|
|
57
62
|
```
|
|
@@ -67,11 +72,11 @@ pipeline.step service_class: MyOtherServiceClass, to_s: 'Second step'
|
|
|
67
72
|
pipeline.step :job, job_class: MyJobClass # to_s is optional
|
|
68
73
|
pipeline.step :job, job_class: MyOtherJobClass
|
|
69
74
|
|
|
70
|
-
pipeline.step :step_name_for_better_log do |_, arg
|
|
75
|
+
pipeline.step :step_name_for_better_log do |_, arg:|
|
|
71
76
|
# ...
|
|
72
77
|
end
|
|
73
78
|
|
|
74
|
-
pipeline.step to_s: 'This is the same as above' do |step, arg
|
|
79
|
+
pipeline.step to_s: 'This is the same as above' do |step, arg:|
|
|
75
80
|
# ... step.to_s => 'This is the same as above'
|
|
76
81
|
end
|
|
77
82
|
```
|
|
@@ -85,11 +90,11 @@ will be set to :inline.
|
|
|
85
90
|
You can then execute the steps with:
|
|
86
91
|
|
|
87
92
|
```ruby
|
|
88
|
-
pipeline.execute('initial argument')
|
|
93
|
+
pipeline.execute(arg: 'initial argument')
|
|
89
94
|
|
|
90
95
|
# Or run the steps directly using block syntax
|
|
91
96
|
|
|
92
|
-
pipeline.execute('initial argument') do |p|
|
|
97
|
+
pipeline.execute(arg: 'initial argument') do |p|
|
|
93
98
|
p.step :service, service_class: MyServiceClass, to_s: 'First step'
|
|
94
99
|
p.step :service, service_class: MyOtherServiceClass, to_s: 'Second step'
|
|
95
100
|
p.step :job, job_class: MyJobClass # to_s is optional
|
|
@@ -101,9 +106,9 @@ end
|
|
|
101
106
|
You can also directly execute a pipeline with:
|
|
102
107
|
|
|
103
108
|
```ruby
|
|
104
|
-
NxtPipeline::Pipeline.execute('initial argument') do |p|
|
|
105
|
-
p.step do |_, arg
|
|
106
|
-
arg.upcase
|
|
109
|
+
NxtPipeline::Pipeline.execute(arg: 'initial argument') do |p|
|
|
110
|
+
p.step do |_, arg:|
|
|
111
|
+
{ arg: arg.upcase }
|
|
107
112
|
end
|
|
108
113
|
end
|
|
109
114
|
```
|
|
@@ -132,8 +137,8 @@ You can also define guard clauses that take a proc to prevent the execution of a
|
|
|
132
137
|
When the guard takes an argument the step argument is yielded.
|
|
133
138
|
|
|
134
139
|
```ruby
|
|
135
|
-
pipeline.execute('initial argument') do |p|
|
|
136
|
-
p.step :service, service_class: MyServiceClass, if: -> (arg) { arg == 'initial argument' }
|
|
140
|
+
pipeline.execute(arg: 'initial argument') do |p|
|
|
141
|
+
p.step :service, service_class: MyServiceClass, if: -> (arg:) { arg == 'initial argument' }
|
|
137
142
|
p.step :service, service_class: MyOtherServiceClass, unless: -> { false }
|
|
138
143
|
end
|
|
139
144
|
|
|
@@ -145,24 +150,24 @@ Apart from defining constructors and steps you can also define error callbacks.
|
|
|
145
150
|
|
|
146
151
|
```ruby
|
|
147
152
|
NxtPipeline::Pipeline.new do |p|
|
|
148
|
-
p.step do |_, arg
|
|
149
|
-
arg.upcase
|
|
153
|
+
p.step do |_, arg:|
|
|
154
|
+
{ arg: arg.upcase }
|
|
150
155
|
end
|
|
151
156
|
|
|
152
|
-
p.on_error MyCustomError do |step,
|
|
157
|
+
p.on_error MyCustomError do |step, opts, error|
|
|
153
158
|
# First matching error callback will be executed!
|
|
154
159
|
end
|
|
155
160
|
|
|
156
|
-
p.on_errors ArgumentError, KeyError do |step,
|
|
161
|
+
p.on_errors ArgumentError, KeyError do |step, opts, error|
|
|
157
162
|
# First matching error callback will be executed!
|
|
158
163
|
end
|
|
159
164
|
|
|
160
|
-
p.on_errors YetAnotherError, halt_on_error: false do |step,
|
|
165
|
+
p.on_errors YetAnotherError, halt_on_error: false do |step, opts, error|
|
|
161
166
|
# After executing the callback the pipeline will not halt but continue to
|
|
162
167
|
# execute the next steps.
|
|
163
168
|
end
|
|
164
169
|
|
|
165
|
-
p.on_errors do |step,
|
|
170
|
+
p.on_errors do |step, opts, error|
|
|
166
171
|
# This will match all errors inheriting from StandardError
|
|
167
172
|
end
|
|
168
173
|
end
|
|
@@ -174,12 +179,12 @@ You can also define callbacks that run before and after the `#execute` action. B
|
|
|
174
179
|
|
|
175
180
|
```ruby
|
|
176
181
|
NxtPipeline::Pipeline.new do |p|
|
|
177
|
-
p.before_execute do |pipeline, arg
|
|
182
|
+
p.before_execute do |pipeline, arg:|
|
|
178
183
|
# Will be called from within #execute before entering the first step
|
|
179
184
|
# After any configure block though!
|
|
180
185
|
end
|
|
181
186
|
|
|
182
|
-
p.after_execute do |pipeline, arg
|
|
187
|
+
p.after_execute do |pipeline, arg:|
|
|
183
188
|
# Will be called from within #execute after executing last step
|
|
184
189
|
end
|
|
185
190
|
end
|
|
@@ -187,6 +192,16 @@ end
|
|
|
187
192
|
|
|
188
193
|
Note that the `after_execute` callback will not be called, when an error is raised in one of the steps. See the previous section (_Error callbacks_) for how to define callbacks that run in case of errors.
|
|
189
194
|
|
|
195
|
+
### Step resolvers
|
|
196
|
+
|
|
197
|
+
NxtPipeline is using so called step_resolvers to find the constructor for a given step by the arguments passed in.
|
|
198
|
+
You can also use this if you are not fine with resolving the constructor from the step argument. Check out the
|
|
199
|
+
`nxt_pipeline/spec/step_resolver_spec.rb` for examples how you can implement your own step_resolvers.
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
## Topics
|
|
203
|
+
- Step orchestration (chainable steps)
|
|
204
|
+
- Constructors should take arg as first and step as second arg
|
|
190
205
|
|
|
191
206
|
## Development
|
|
192
207
|
|
data/lib/nxt_pipeline.rb
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module NxtPipeline
|
|
2
|
+
class Constructor
|
|
3
|
+
def initialize(name, **opts, &block)
|
|
4
|
+
@name = name
|
|
5
|
+
@block = block
|
|
6
|
+
@opts = opts
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
attr_reader :opts, :block
|
|
10
|
+
|
|
11
|
+
delegate :arity, to: :block
|
|
12
|
+
|
|
13
|
+
def call(*args, **opts, &block)
|
|
14
|
+
# ActiveSupport's #delegate does not properly handle keyword arg passing
|
|
15
|
+
# in the latest released version. Thefore we bypass delegation by reimplementing
|
|
16
|
+
# the method ourselves. This is already fixed in Rails master though.
|
|
17
|
+
self.block.call(*args, **opts, &block)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module NxtPipeline
|
|
2
2
|
class ErrorCallback
|
|
3
|
-
def initialize(errors, halt_on_error, callback)
|
|
4
|
-
@errors = errors
|
|
3
|
+
def initialize(errors, halt_on_error, &callback)
|
|
4
|
+
@errors = errors.any? ? errors : [StandardError]
|
|
5
5
|
@halt_on_error = halt_on_error
|
|
6
6
|
@callback = callback
|
|
7
7
|
end
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
module NxtPipeline
|
|
2
2
|
class Pipeline
|
|
3
|
-
def self.execute(opts, &block)
|
|
4
|
-
new(&block).execute(opts)
|
|
3
|
+
def self.execute(**opts, &block)
|
|
4
|
+
new(&block).execute(**opts)
|
|
5
5
|
end
|
|
6
6
|
|
|
7
|
-
def initialize(&block)
|
|
7
|
+
def initialize(step_resolvers = default_step_resolvers, &block)
|
|
8
8
|
@steps = []
|
|
9
9
|
@error_callbacks = []
|
|
10
10
|
@logger = Logger.new
|
|
11
11
|
@current_step = nil
|
|
12
12
|
@current_arg = nil
|
|
13
13
|
@default_constructor_name = nil
|
|
14
|
-
@
|
|
14
|
+
@constructors = {}
|
|
15
|
+
@step_resolvers = step_resolvers
|
|
15
16
|
|
|
16
17
|
configure(&block) if block_given?
|
|
17
18
|
end
|
|
@@ -20,17 +21,20 @@ module NxtPipeline
|
|
|
20
21
|
|
|
21
22
|
attr_accessor :logger, :steps
|
|
22
23
|
|
|
23
|
-
# register steps with name and block
|
|
24
24
|
def constructor(name, **opts, &constructor)
|
|
25
25
|
name = name.to_sym
|
|
26
|
-
raise StandardError, "Already registered step :#{name}" if
|
|
26
|
+
raise StandardError, "Already registered step :#{name}" if constructors[name]
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
constructors[name] = Constructor.new(name, **opts, &constructor)
|
|
29
29
|
|
|
30
30
|
return unless opts.fetch(:default, false)
|
|
31
31
|
set_default_constructor(name)
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
+
def step_resolver(&block)
|
|
35
|
+
step_resolvers << block
|
|
36
|
+
end
|
|
37
|
+
|
|
34
38
|
def set_default_constructor(name)
|
|
35
39
|
raise_duplicate_default_constructor if default_constructor_name.present?
|
|
36
40
|
self.default_constructor_name = name
|
|
@@ -40,43 +44,54 @@ module NxtPipeline
|
|
|
40
44
|
raise ArgumentError, 'Default step already defined'
|
|
41
45
|
end
|
|
42
46
|
|
|
43
|
-
def step(
|
|
44
|
-
type = type&.to_sym
|
|
45
|
-
|
|
47
|
+
def step(argument = nil, **opts, &block)
|
|
46
48
|
constructor = if block_given?
|
|
47
49
|
# make type the :to_s of inline steps
|
|
48
50
|
# fall back to :inline if no type is given
|
|
49
|
-
|
|
50
|
-
opts.reverse_merge!(to_s:
|
|
51
|
-
block
|
|
51
|
+
argument ||= :inline
|
|
52
|
+
opts.reverse_merge!(to_s: argument)
|
|
53
|
+
Constructor.new(:inline, **opts, &block)
|
|
52
54
|
else
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
constructor = step_resolvers.lazy.map do |resolver|
|
|
56
|
+
resolver.call(argument)
|
|
57
|
+
end.find(&:itself)
|
|
58
|
+
|
|
59
|
+
if constructor
|
|
60
|
+
constructor && constructors.fetch(constructor) { raise KeyError, "No step :#{argument} registered" }
|
|
61
|
+
elsif default_constructor
|
|
62
|
+
argument ||= default_constructor_name
|
|
63
|
+
default_constructor
|
|
56
64
|
else
|
|
57
|
-
|
|
58
|
-
type = default_constructor_name
|
|
59
|
-
# If none was given - raise
|
|
60
|
-
default_constructor || (raise StandardError, 'No default step registered')
|
|
65
|
+
raise StandardError, "Could not resolve step from: #{argument}"
|
|
61
66
|
end
|
|
62
67
|
end
|
|
63
68
|
|
|
64
|
-
steps << Step.new(
|
|
69
|
+
steps << Step.new(argument, constructor, steps.count, **opts)
|
|
65
70
|
end
|
|
66
71
|
|
|
67
|
-
def execute(
|
|
72
|
+
def execute(**changeset, &block)
|
|
68
73
|
reset
|
|
69
74
|
|
|
70
75
|
configure(&block) if block_given?
|
|
71
|
-
before_execute_callback.call(self,
|
|
76
|
+
before_execute_callback.call(self, changeset) if before_execute_callback.respond_to?(:call)
|
|
72
77
|
|
|
73
|
-
result = steps.inject(
|
|
74
|
-
execute_step(step,
|
|
78
|
+
result = steps.inject(changeset) do |changeset, step|
|
|
79
|
+
execute_step(step, **changeset)
|
|
75
80
|
rescue StandardError => error
|
|
81
|
+
logger_for_error = logger
|
|
82
|
+
|
|
83
|
+
error.define_singleton_method :details do
|
|
84
|
+
OpenStruct.new(
|
|
85
|
+
changeset: changeset,
|
|
86
|
+
logger: logger_for_error,
|
|
87
|
+
step: step
|
|
88
|
+
)
|
|
89
|
+
end
|
|
90
|
+
|
|
76
91
|
callback = find_error_callback(error)
|
|
77
92
|
raise unless callback && callback.continue_after_error?
|
|
78
93
|
handle_step_error(error)
|
|
79
|
-
|
|
94
|
+
changeset
|
|
80
95
|
end
|
|
81
96
|
|
|
82
97
|
after_execute_callback.call(self, result) if after_execute_callback.respond_to?(:call)
|
|
@@ -95,7 +110,7 @@ module NxtPipeline
|
|
|
95
110
|
end
|
|
96
111
|
|
|
97
112
|
def on_errors(*errors, halt_on_error: true, &callback)
|
|
98
|
-
error_callbacks << ErrorCallback.new(errors, halt_on_error, callback)
|
|
113
|
+
error_callbacks << ErrorCallback.new(errors, halt_on_error, &callback)
|
|
99
114
|
end
|
|
100
115
|
|
|
101
116
|
alias :on_error :on_errors
|
|
@@ -110,7 +125,7 @@ module NxtPipeline
|
|
|
110
125
|
|
|
111
126
|
private
|
|
112
127
|
|
|
113
|
-
attr_reader :error_callbacks, :
|
|
128
|
+
attr_reader :error_callbacks, :constructors, :step_resolvers
|
|
114
129
|
attr_accessor :current_step,
|
|
115
130
|
:current_arg,
|
|
116
131
|
:default_constructor_name,
|
|
@@ -120,15 +135,15 @@ module NxtPipeline
|
|
|
120
135
|
def default_constructor
|
|
121
136
|
return unless default_constructor_name
|
|
122
137
|
|
|
123
|
-
@default_constructor ||=
|
|
138
|
+
@default_constructor ||= constructors[default_constructor_name.to_sym]
|
|
124
139
|
end
|
|
125
140
|
|
|
126
|
-
def execute_step(step,
|
|
141
|
+
def execute_step(step, **changeset)
|
|
127
142
|
self.current_step = step
|
|
128
|
-
self.current_arg =
|
|
129
|
-
result = step.execute(
|
|
143
|
+
self.current_arg = changeset
|
|
144
|
+
result = step.execute(**changeset)
|
|
130
145
|
log_step(step)
|
|
131
|
-
result ||
|
|
146
|
+
result || changeset
|
|
132
147
|
end
|
|
133
148
|
|
|
134
149
|
def find_error_callback(error)
|
|
@@ -149,5 +164,9 @@ module NxtPipeline
|
|
|
149
164
|
def raise_reserved_type_inline_error
|
|
150
165
|
raise ArgumentError, 'Type :inline is reserved for inline steps!'
|
|
151
166
|
end
|
|
167
|
+
|
|
168
|
+
def default_step_resolvers
|
|
169
|
+
[->(step_argument) { step_argument.is_a?(Symbol) && step_argument }]
|
|
170
|
+
end
|
|
152
171
|
end
|
|
153
172
|
end
|
data/lib/nxt_pipeline/step.rb
CHANGED
|
@@ -1,26 +1,42 @@
|
|
|
1
1
|
module NxtPipeline
|
|
2
2
|
class Step
|
|
3
|
-
def initialize(
|
|
3
|
+
def initialize(argument, constructor, index, **opts)
|
|
4
4
|
define_attr_readers(opts)
|
|
5
5
|
|
|
6
|
-
@
|
|
6
|
+
@argument = argument
|
|
7
7
|
@index = index
|
|
8
|
-
@result = nil
|
|
9
8
|
@opts = opts
|
|
10
|
-
@status = nil
|
|
11
9
|
@constructor = constructor
|
|
10
|
+
@to_s = "#{opts.merge(argument: argument)}"
|
|
11
|
+
@options_mapper = opts[:map_options]
|
|
12
|
+
|
|
13
|
+
@status = nil
|
|
14
|
+
@result = nil
|
|
12
15
|
@error = nil
|
|
16
|
+
@mapped_options = nil
|
|
13
17
|
end
|
|
14
18
|
|
|
15
|
-
attr_reader :
|
|
19
|
+
attr_reader :argument, :result, :status, :error, :opts, :index, :mapped_options
|
|
20
|
+
attr_accessor :to_s
|
|
21
|
+
|
|
22
|
+
alias_method :name=, :to_s=
|
|
23
|
+
alias_method :name, :to_s
|
|
24
|
+
|
|
25
|
+
def execute(**changeset)
|
|
26
|
+
mapper = options_mapper || default_options_mapper
|
|
27
|
+
mapper_args = [changeset, self].take(mapper.arity)
|
|
28
|
+
self.mapped_options = mapper.call(*mapper_args)
|
|
29
|
+
|
|
30
|
+
guard_args = [changeset, self]
|
|
16
31
|
|
|
17
|
-
def execute(arg)
|
|
18
|
-
guard_args = [arg, self]
|
|
19
32
|
if_guard_args = guard_args.take(if_guard.arity)
|
|
20
33
|
unless_guard_guard_args = guard_args.take(unless_guard.arity)
|
|
21
34
|
|
|
22
|
-
if unless_guard
|
|
23
|
-
|
|
35
|
+
if !instrumentalize_callable(unless_guard, unless_guard_guard_args) && instrumentalize_callable(if_guard, if_guard_args)
|
|
36
|
+
constructor_args = [self, changeset]
|
|
37
|
+
constructor_args = constructor_args.take(constructor.arity)
|
|
38
|
+
|
|
39
|
+
self.result = instrumentalize_callable(constructor, constructor_args)
|
|
24
40
|
end
|
|
25
41
|
|
|
26
42
|
set_status
|
|
@@ -31,29 +47,33 @@ module NxtPipeline
|
|
|
31
47
|
raise
|
|
32
48
|
end
|
|
33
49
|
|
|
34
|
-
def
|
|
35
|
-
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def type?(potential_type)
|
|
39
|
-
type.to_sym == potential_type.to_sym
|
|
40
|
-
end
|
|
50
|
+
# def type?(potential_type)
|
|
51
|
+
# constructor.resolve_type(potential_type)
|
|
52
|
+
# end
|
|
41
53
|
|
|
42
54
|
private
|
|
43
55
|
|
|
44
|
-
attr_writer :result, :status, :error
|
|
45
|
-
attr_reader :constructor
|
|
56
|
+
attr_writer :result, :status, :error, :mapped_options
|
|
57
|
+
attr_reader :constructor, :options_mapper
|
|
58
|
+
|
|
59
|
+
def instrumentalize_callable(callable, args)
|
|
60
|
+
if args.last.is_a?(Hash)
|
|
61
|
+
callable.call(*args.take(args.length - 1), **args.last)
|
|
62
|
+
else
|
|
63
|
+
callable.call(*args)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
46
66
|
|
|
47
67
|
def if_guard
|
|
48
|
-
opts.fetch(:if) {
|
|
68
|
+
opts.fetch(:if) { guard(true) }
|
|
49
69
|
end
|
|
50
70
|
|
|
51
71
|
def unless_guard
|
|
52
|
-
opts.fetch(:unless) {
|
|
72
|
+
opts.fetch(:unless) { guard(false) }
|
|
53
73
|
end
|
|
54
74
|
|
|
55
|
-
def
|
|
56
|
-
-> {
|
|
75
|
+
def guard(result)
|
|
76
|
+
-> { result }
|
|
57
77
|
end
|
|
58
78
|
|
|
59
79
|
def define_attr_readers(opts)
|
|
@@ -67,5 +87,10 @@ module NxtPipeline
|
|
|
67
87
|
def set_status
|
|
68
88
|
self.status = result.present? ? :success : :skipped
|
|
69
89
|
end
|
|
90
|
+
|
|
91
|
+
def default_options_mapper
|
|
92
|
+
# returns an empty hash
|
|
93
|
+
->(changeset) { {} }
|
|
94
|
+
end
|
|
70
95
|
end
|
|
71
96
|
end
|
data/lib/nxt_pipeline/version.rb
CHANGED
data/nxt_pipeline.gemspec
CHANGED
|
@@ -35,9 +35,9 @@ Gem::Specification.new do |spec|
|
|
|
35
35
|
spec.require_paths = ["lib"]
|
|
36
36
|
|
|
37
37
|
spec.add_dependency "activesupport"
|
|
38
|
-
spec.add_development_dependency "bundler", "~> 1
|
|
38
|
+
spec.add_development_dependency "bundler", "~> 2.1"
|
|
39
39
|
spec.add_development_dependency "guard-rspec"
|
|
40
|
-
spec.add_development_dependency "rake", "~>
|
|
40
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
|
41
41
|
spec.add_development_dependency "rspec", "~> 3.0"
|
|
42
|
-
spec.add_development_dependency "pry"
|
|
42
|
+
spec.add_development_dependency "pry-byebug"
|
|
43
43
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: nxt_pipeline
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2
|
|
4
|
+
version: 0.4.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Nils Sommer
|
|
@@ -10,7 +10,7 @@ authors:
|
|
|
10
10
|
autorequire:
|
|
11
11
|
bindir: exe
|
|
12
12
|
cert_chain: []
|
|
13
|
-
date:
|
|
13
|
+
date: 2020-10-13 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: activesupport
|
|
@@ -32,14 +32,14 @@ dependencies:
|
|
|
32
32
|
requirements:
|
|
33
33
|
- - "~>"
|
|
34
34
|
- !ruby/object:Gem::Version
|
|
35
|
-
version: '1
|
|
35
|
+
version: '2.1'
|
|
36
36
|
type: :development
|
|
37
37
|
prerelease: false
|
|
38
38
|
version_requirements: !ruby/object:Gem::Requirement
|
|
39
39
|
requirements:
|
|
40
40
|
- - "~>"
|
|
41
41
|
- !ruby/object:Gem::Version
|
|
42
|
-
version: '1
|
|
42
|
+
version: '2.1'
|
|
43
43
|
- !ruby/object:Gem::Dependency
|
|
44
44
|
name: guard-rspec
|
|
45
45
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -60,14 +60,14 @@ dependencies:
|
|
|
60
60
|
requirements:
|
|
61
61
|
- - "~>"
|
|
62
62
|
- !ruby/object:Gem::Version
|
|
63
|
-
version: '
|
|
63
|
+
version: '13.0'
|
|
64
64
|
type: :development
|
|
65
65
|
prerelease: false
|
|
66
66
|
version_requirements: !ruby/object:Gem::Requirement
|
|
67
67
|
requirements:
|
|
68
68
|
- - "~>"
|
|
69
69
|
- !ruby/object:Gem::Version
|
|
70
|
-
version: '
|
|
70
|
+
version: '13.0'
|
|
71
71
|
- !ruby/object:Gem::Dependency
|
|
72
72
|
name: rspec
|
|
73
73
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -83,7 +83,7 @@ dependencies:
|
|
|
83
83
|
- !ruby/object:Gem::Version
|
|
84
84
|
version: '3.0'
|
|
85
85
|
- !ruby/object:Gem::Dependency
|
|
86
|
-
name: pry
|
|
86
|
+
name: pry-byebug
|
|
87
87
|
requirement: !ruby/object:Gem::Requirement
|
|
88
88
|
requirements:
|
|
89
89
|
- - ">="
|
|
@@ -105,6 +105,7 @@ extra_rdoc_files: []
|
|
|
105
105
|
files:
|
|
106
106
|
- ".circleci/config.yml"
|
|
107
107
|
- ".gitignore"
|
|
108
|
+
- ".pryrc"
|
|
108
109
|
- ".rspec"
|
|
109
110
|
- ".ruby-version"
|
|
110
111
|
- ".travis.yml"
|
|
@@ -120,6 +121,7 @@ files:
|
|
|
120
121
|
- bin/rspec
|
|
121
122
|
- bin/setup
|
|
122
123
|
- lib/nxt_pipeline.rb
|
|
124
|
+
- lib/nxt_pipeline/constructor.rb
|
|
123
125
|
- lib/nxt_pipeline/error_callback.rb
|
|
124
126
|
- lib/nxt_pipeline/logger.rb
|
|
125
127
|
- lib/nxt_pipeline/pipeline.rb
|
|
@@ -148,7 +150,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
148
150
|
- !ruby/object:Gem::Version
|
|
149
151
|
version: '0'
|
|
150
152
|
requirements: []
|
|
151
|
-
rubygems_version: 3.
|
|
153
|
+
rubygems_version: 3.1.2
|
|
152
154
|
signing_key:
|
|
153
155
|
specification_version: 4
|
|
154
156
|
summary: DSL to build Pipeline with mountable Segments to process things.
|