nxt_pipeline 0.4.2 → 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/Gemfile.lock +1 -1
- data/README.md +35 -32
- data/lib/nxt_pipeline/step.rb +54 -24
- data/lib/nxt_pipeline/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0f47be27dd03af5d8a11274b4667a40e2a0c14b4be0a373dd90e1fc7deb93c03
|
4
|
+
data.tar.gz: 6964e21671bb458e187dd3289538e49243e42b06c38c804ffc2b69ed94146612
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5ba8339e42e2e485e9c0c00a35d6df56324b1145605d564039a4931d384d0297ef44b3613c8e45e83dfcfea83f0ed7b5a377f3a6e89f2a03e5b9dbfcc6e47b9a
|
7
|
+
data.tar.gz: f9c938b9302bf9f2b4c126ddaa1b978b99c2f02fe1cdbc6d17be307135a22a504e002c6b110fa0b2eb92a04b5623f4293c8f92575c82ad2240f3de0b4a49a8ad
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
## nxt_pipeline 0.4.3 (October 20, 2020)
|
2
|
+
|
3
|
+
Add new attribute readers on step object.
|
4
|
+
|
5
|
+
After executing a step execution_finished_at execution_started_at and execution_duration
|
6
|
+
will be set and can be accessed via attribute readers.
|
7
|
+
|
1
8
|
## nxt_pipeline 0.4.2 (October 12, 2020)
|
2
9
|
|
3
10
|
* 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
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -24,35 +24,35 @@ Or install it yourself as:
|
|
24
24
|
|
25
25
|
### Constructors
|
26
26
|
|
27
|
-
First you probably want to configure a pipeline so that it can execute your steps.
|
28
|
-
Therefore you want to define constructors for your steps. Constructors take a name
|
27
|
+
First you probably want to configure a pipeline so that it can execute your steps.
|
28
|
+
Therefore you want to define constructors for your steps. Constructors take a name
|
29
29
|
as the first argument and step options as the second. All step options are being exposed
|
30
|
-
by the step yielded to the constructor.
|
30
|
+
by the step yielded to the constructor.
|
31
31
|
|
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
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.
|
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
37
|
p.constructor(:service, default: true) do |step, arg:|
|
38
38
|
step.to_s = step.service_class.to_s
|
39
39
|
result = step.service_class.new(options: arg).call
|
40
40
|
result && { arg: result }
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
p.constructor(:job) do |step, arg:|
|
44
44
|
step.job_class.perform_later(*arg) && { arg: arg }
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
-
# Once a pipeline was created you can still configure it
|
48
|
+
# Once a pipeline was created you can still configure it
|
49
49
|
pipeline.constructor(:call) do |step, arg:|
|
50
50
|
result = step.caller.new(arg).call
|
51
51
|
result && { arg: result }
|
52
52
|
end
|
53
53
|
|
54
|
-
# same with block syntax
|
55
|
-
# You can use this to split up execution from configuration
|
54
|
+
# same with block syntax
|
55
|
+
# You can use this to split up execution from configuration
|
56
56
|
pipeline.configure do |p|
|
57
57
|
p.constructor(:call) do |step, arg:|
|
58
58
|
result = step.caller.new(arg).call
|
@@ -61,13 +61,13 @@ pipeline.configure do |p|
|
|
61
61
|
end
|
62
62
|
```
|
63
63
|
|
64
|
-
### Defining steps
|
64
|
+
### Defining steps
|
65
65
|
|
66
66
|
Once your pipeline knows how to execute your steps you can add those.
|
67
67
|
|
68
68
|
```ruby
|
69
69
|
pipeline.step :service, service_class: MyServiceClass, to_s: 'First step'
|
70
|
-
pipeline.step service_class: MyOtherServiceClass, to_s: 'Second step'
|
70
|
+
pipeline.step service_class: MyOtherServiceClass, to_s: 'Second step'
|
71
71
|
# ^ Since service is the default step you don't have to specify it the step type each time
|
72
72
|
pipeline.step :job, job_class: MyJobClass # to_s is optional
|
73
73
|
pipeline.step :job, job_class: MyOtherJobClass
|
@@ -82,12 +82,12 @@ end
|
|
82
82
|
```
|
83
83
|
|
84
84
|
You can also define inline steps, meaning the block will be executed. When you do not provide a :to_s option, type
|
85
|
-
will be used as :to_s option per default. When no type was given for an inline block the type of the inline block
|
86
|
-
will be set to :inline.
|
85
|
+
will be used as :to_s option per default. When no type was given for an inline block the type of the inline block
|
86
|
+
will be set to :inline.
|
87
87
|
|
88
88
|
### Execution
|
89
89
|
|
90
|
-
You can then execute the steps with:
|
90
|
+
You can then execute the steps with:
|
91
91
|
|
92
92
|
```ruby
|
93
93
|
pipeline.execute(arg: 'initial argument')
|
@@ -111,13 +111,13 @@ NxtPipeline::Pipeline.execute(arg: 'initial argument') do |p|
|
|
111
111
|
{ arg: arg.upcase }
|
112
112
|
end
|
113
113
|
end
|
114
|
-
```
|
114
|
+
```
|
115
115
|
|
116
|
-
You can query the steps of your pipeline simply by calling `pipeline.steps`. A NxtPipeline::Step will provide you with
|
117
|
-
an interface to it's type, options, status (:success, :skipped, :failed), result, error and the index in the pipeline.
|
116
|
+
You can query the steps of your pipeline simply by calling `pipeline.steps`. A NxtPipeline::Step will provide you with
|
117
|
+
an interface to it's type, options, status (:success, :skipped, :failed), execution_finished_at execution_started_at, execution_duration, result, error and the index in the pipeline.
|
118
118
|
|
119
119
|
```
|
120
|
-
pipeline.steps.first
|
120
|
+
pipeline.steps.first
|
121
121
|
# will give you something like this:
|
122
122
|
|
123
123
|
#<NxtPipeline::Step:0x00007f83eb399448
|
@@ -128,20 +128,23 @@ pipeline.steps.first
|
|
128
128
|
@opts={:to_s=>:transformer, :method=>:upcase},
|
129
129
|
@result=nil,
|
130
130
|
@status=nil,
|
131
|
-
@type=:transformer
|
132
|
-
|
131
|
+
@type=:transformer
|
132
|
+
@execution_duration=1.0e-05,
|
133
|
+
@execution_finished_at=2020-10-22 15:52:55.806417 +0100,
|
134
|
+
@execution_started_at=2020-10-22 15:52:55.806407 +0100,>
|
135
|
+
```
|
133
136
|
|
134
137
|
### Guard clauses
|
135
138
|
|
136
139
|
You can also define guard clauses that take a proc to prevent the execution of a step.
|
137
|
-
When the guard takes an argument the step argument is yielded.
|
140
|
+
When the guard takes an argument the step argument is yielded.
|
138
141
|
|
139
142
|
```ruby
|
140
143
|
pipeline.execute(arg: 'initial argument') do |p|
|
141
144
|
p.step :service, service_class: MyServiceClass, if: -> (arg:) { arg == 'initial argument' }
|
142
145
|
p.step :service, service_class: MyOtherServiceClass, unless: -> { false }
|
143
146
|
end
|
144
|
-
|
147
|
+
|
145
148
|
```
|
146
149
|
|
147
150
|
### Error callbacks
|
@@ -153,25 +156,25 @@ NxtPipeline::Pipeline.new do |p|
|
|
153
156
|
p.step do |_, arg:|
|
154
157
|
{ arg: arg.upcase }
|
155
158
|
end
|
156
|
-
|
159
|
+
|
157
160
|
p.on_error MyCustomError do |step, opts, error|
|
158
161
|
# First matching error callback will be executed!
|
159
162
|
end
|
160
|
-
|
163
|
+
|
161
164
|
p.on_errors ArgumentError, KeyError do |step, opts, error|
|
162
165
|
# First matching error callback will be executed!
|
163
166
|
end
|
164
|
-
|
167
|
+
|
165
168
|
p.on_errors YetAnotherError, halt_on_error: false do |step, opts, error|
|
166
169
|
# After executing the callback the pipeline will not halt but continue to
|
167
170
|
# execute the next steps.
|
168
171
|
end
|
169
|
-
|
172
|
+
|
170
173
|
p.on_errors do |step, opts, error|
|
171
174
|
# This will match all errors inheriting from StandardError
|
172
175
|
end
|
173
176
|
end
|
174
|
-
```
|
177
|
+
```
|
175
178
|
|
176
179
|
### Before and After callbacks
|
177
180
|
|
@@ -181,27 +184,27 @@ You can also define callbacks that run before and after the `#execute` action. B
|
|
181
184
|
NxtPipeline::Pipeline.new do |p|
|
182
185
|
p.before_execute do |pipeline, arg:|
|
183
186
|
# Will be called from within #execute before entering the first step
|
184
|
-
# After any configure block though!
|
187
|
+
# After any configure block though!
|
185
188
|
end
|
186
|
-
|
189
|
+
|
187
190
|
p.after_execute do |pipeline, arg:|
|
188
191
|
# Will be called from within #execute after executing last step
|
189
192
|
end
|
190
193
|
end
|
191
194
|
```
|
192
195
|
|
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.
|
196
|
+
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.
|
194
197
|
|
195
198
|
### Step resolvers
|
196
199
|
|
197
200
|
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.
|
201
|
+
You can also use this if you are not fine with resolving the constructor from the step argument. Check out the
|
202
|
+
`nxt_pipeline/spec/step_resolver_spec.rb` for examples how you can implement your own step_resolvers.
|
200
203
|
|
201
204
|
|
202
205
|
## Topics
|
203
206
|
- Step orchestration (chainable steps)
|
204
|
-
- Constructors should take arg as first and step as second arg
|
207
|
+
- Constructors should take arg as first and step as second arg
|
205
208
|
|
206
209
|
## Development
|
207
210
|
|
data/lib/nxt_pipeline/step.rb
CHANGED
@@ -16,47 +16,57 @@ module NxtPipeline
|
|
16
16
|
@mapped_options = nil
|
17
17
|
end
|
18
18
|
|
19
|
-
attr_reader :argument, :result, :status, :error, :opts, :index, :mapped_options
|
19
|
+
attr_reader :argument, :result, :status, :execution_started_at, :execution_finished_at, :execution_duration, :error, :opts, :index, :mapped_options
|
20
20
|
attr_accessor :to_s
|
21
21
|
|
22
22
|
alias_method :name=, :to_s=
|
23
23
|
alias_method :name, :to_s
|
24
24
|
|
25
25
|
def execute(**changeset)
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
guard_args = [changeset, self]
|
26
|
+
track_execution_time do
|
27
|
+
set_mapped_options(changeset)
|
28
|
+
guard_args = [changeset, self]
|
31
29
|
|
32
|
-
|
33
|
-
|
34
|
-
|
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)
|
30
|
+
if evaluate_unless_guard(guard_args) && evaluate_if_guard(guard_args)
|
31
|
+
self.result = construct_result(changeset)
|
32
|
+
end
|
38
33
|
|
39
|
-
|
34
|
+
set_status
|
35
|
+
result
|
40
36
|
end
|
41
|
-
|
42
|
-
set_status
|
43
|
-
result
|
44
37
|
rescue StandardError => e
|
45
38
|
self.status = :failed
|
46
39
|
self.error = e
|
47
40
|
raise
|
48
41
|
end
|
49
42
|
|
50
|
-
|
51
|
-
|
52
|
-
|
43
|
+
def set_mapped_options(changeset)
|
44
|
+
mapper = options_mapper || default_options_mapper
|
45
|
+
mapper_args = [changeset, self].take(mapper.arity)
|
46
|
+
self.mapped_options = mapper.call(*mapper_args)
|
47
|
+
end
|
53
48
|
|
54
49
|
private
|
55
50
|
|
56
|
-
attr_writer :result, :status, :error, :mapped_options
|
51
|
+
attr_writer :result, :status, :error, :mapped_options, :execution_started_at, :execution_finished_at, :execution_duration
|
57
52
|
attr_reader :constructor, :options_mapper
|
58
|
-
|
59
|
-
def
|
53
|
+
|
54
|
+
def evaluate_if_guard(args)
|
55
|
+
execute_callable(if_guard, args)
|
56
|
+
end
|
57
|
+
|
58
|
+
def evaluate_unless_guard(args)
|
59
|
+
!execute_callable(unless_guard, args)
|
60
|
+
end
|
61
|
+
|
62
|
+
def construct_result(changeset)
|
63
|
+
args = [self, changeset]
|
64
|
+
execute_callable(constructor, args)
|
65
|
+
end
|
66
|
+
|
67
|
+
def execute_callable(callable, args)
|
68
|
+
args = args.take(callable.arity)
|
69
|
+
|
60
70
|
if args.last.is_a?(Hash)
|
61
71
|
callable.call(*args.take(args.length - 1), **args.last)
|
62
72
|
else
|
@@ -88,9 +98,29 @@ module NxtPipeline
|
|
88
98
|
self.status = result.present? ? :success : :skipped
|
89
99
|
end
|
90
100
|
|
101
|
+
def track_execution_time(&block)
|
102
|
+
set_execution_started_at
|
103
|
+
block.call
|
104
|
+
ensure
|
105
|
+
set_execution_finished_at
|
106
|
+
set_execution_duration
|
107
|
+
end
|
108
|
+
|
109
|
+
def set_execution_started_at
|
110
|
+
self.execution_started_at = Time.current
|
111
|
+
end
|
112
|
+
|
113
|
+
def set_execution_finished_at
|
114
|
+
self.execution_finished_at = Time.current
|
115
|
+
end
|
116
|
+
|
117
|
+
def set_execution_duration
|
118
|
+
self.execution_duration = execution_finished_at - execution_started_at
|
119
|
+
end
|
120
|
+
|
91
121
|
def default_options_mapper
|
92
122
|
# returns an empty hash
|
93
|
-
->(
|
123
|
+
->(_) { {} }
|
94
124
|
end
|
95
125
|
end
|
96
|
-
end
|
126
|
+
end
|
data/lib/nxt_pipeline/version.rb
CHANGED
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.4.
|
4
|
+
version: 0.4.3
|
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: 2020-10-
|
13
|
+
date: 2020-10-23 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activesupport
|