Skip to content

Commit 804aeca

Browse files
authored
feat!: improve callback api (#8)
* docs(readme): add section about GitHub flow * docs(readme): update CI badge * feat!: change SCP before_all callback #6 * feat!: change SCP after_all callback #6 * feat!: change SCP before_each callback #6 * feat!: change SCP after_each callback #6 * docs: update CHANGELOG
1 parent a13d1ab commit 804aeca

File tree

7 files changed

+150
-55
lines changed

7 files changed

+150
-55
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ Types of changes:
1616

1717
## [Unreleased]
1818

19+
### Changed
20+
21+
* `Flows::SharedContextPipeline` callback API, GitHub issue: #6
22+
1923
## [0.4.0] - 2020-04-21
2024

2125
### Added

README.md

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Flows
22

3-
[![Build Status](https://github.com/ffloyd/flows/workflows/Build/badge.svg)](https://github.com/ffloyd/flows/actions)
3+
[![Build Status](https://github.com/ffloyd/flows/workflows/Test/badge.svg)](https://github.com/ffloyd/flows/actions)
44
[![codecov](https://codecov.io/gh/ffloyd/flows/branch/master/graph/badge.svg)](https://codecov.io/gh/ffloyd/flows)
55
[![Gem Version](https://badge.fury.io/rb/flows.svg)](https://badge.fury.io/rb/flows)
66

@@ -251,6 +251,16 @@ version. _No exceptions._
251251

252252
Commit with a version bump should contain _only_ version bump and CHANGELOG.md update.
253253

254+
### GitHub Flow
255+
256+
Since `v0.4.0` this repo strictly follow [GitHub
257+
Flow](https://guides.github.com/introduction/flow/) with some additions:
258+
259+
* branch naming using dash: `improved-contexts`
260+
* use [references to
261+
issues](https://help.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword)
262+
in commit messages and CHANGELOG.md
263+
254264
### Planned features for v1.0.0
255265

256266
* validation framework

docs/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Flows
22

3-
[![Build Status](https://github.com/ffloyd/flows/workflows/Build/badge.svg)](https://github.com/ffloyd/flows/actions)
3+
[![Build Status](https://github.com/ffloyd/flows/workflows/Test/badge.svg)](https://github.com/ffloyd/flows/actions)
44
[![codecov](https://codecov.io/gh/ffloyd/flows/branch/master/graph/badge.svg)](https://codecov.io/gh/ffloyd/flows)
55
[![Gem Version](https://badge.fury.io/rb/flows.svg)](https://badge.fury.io/rb/flows)
66

lib/flows/shared_context_pipeline.rb

+28-17
Original file line numberDiff line numberDiff line change
@@ -140,35 +140,45 @@ module Flows
140140
# # steps implementations here
141141
# end
142142
#
143-
# ## Callbacks
143+
# ## Callbacks and metadata
144144
#
145145
# You may want to have some logic to execute before all steps, or after all, or before each, or after each.
146146
# For example to inject generalized execution process logging.
147147
# To achieve this you can use callbacks:
148148
#
149149
# class MySCP < Flows::SharedContextPipeline
150-
# before_all do |klass, context|
151-
# # you can modify execution context here
150+
# before_all do |klass, data, meta|
151+
# # you can modify execution data context and metadata here
152152
# # return value will be ignored
153153
# end
154154
#
155-
# after_all do |klass, pipeline_result|
156-
# # you must provide final result object for pipeline here
155+
# after_all do |klass, pipeline_result, data, meta|
156+
# # you can modify execution data context and metadata here
157+
# # you must return a final result object here
157158
# # if no modifications needed - just return provided pipeline_result
158159
# end
159160
#
160-
# before_each do |klass, step_name, context|
161-
# # you can modify context here
161+
# before_each do |klass, step_name, data, meta|
162+
# # you can modify execution data context and metadata here
162163
# # return value will be ignored
163164
# end
164165
#
165-
# after_each do |klass, step_name, context, step_result|
166-
# # you can modify context here
167-
# # you must not modify step_result
168-
# # context already has data from step_result at the moment of execution
166+
# after_each do |klass, step_name, step_result, data, meta|
167+
# # you can modify execution data context and metadata here
169168
# # return value will be ignored
169+
# #
170+
# # callback executed after context is updated with result data
171+
# # (in the case of normal steps, mutation steps update context directly)
172+
# #
173+
# # DO NOT MODIFY RESULT OBJECT HERE - IT CAN BROKE MUTATION STEPS
170174
# end
171175
# end
176+
#
177+
# Metadata - is a Hash which is shared between step executions.
178+
# This hash becomes metadata of a final {Flows::Result}.
179+
#
180+
# Metadata is designed to store non-business data such as execution times,
181+
# some library specific data, and so on.
172182
class SharedContextPipeline
173183
extend ::Flows::Plugin::ImplicitInit
174184

@@ -192,24 +202,25 @@ def initialize
192202
# Executes pipeline with provided keyword arguments, returns Result Object.
193203
#
194204
# @return [Flows::Result]
195-
def call(**kwargs) # rubocop:disable Metrics/MethodLength
205+
def call(**data) # rubocop:disable Metrics/MethodLength
196206
klass = self.class
197-
context = { data: kwargs, class: klass }
207+
meta = {}
208+
context = { data: data, meta: meta, class: klass }
198209

199210
klass.before_all_callbacks.each do |callback|
200-
callback.call(klass, context[:data])
211+
callback.call(klass, data, meta)
201212
end
202213

203214
flow_result = @__flow.call(nil, context: context)
204215

205216
final_result = flow_result.class.new(
206-
context[:data],
217+
data,
207218
status: flow_result.status,
208-
meta: { last_step: context[:last_step] }
219+
meta: meta
209220
)
210221

211222
klass.after_all_callbacks.reduce(final_result) do |result, callback|
212-
callback.call(klass, result)
223+
callback.call(klass, result, data, meta)
213224
end
214225
end
215226
end

lib/flows/shared_context_pipeline/mutation_step.rb

+6-8
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,26 @@
11
module Flows
22
class SharedContextPipeline
33
EMPTY_HASH = {}.freeze
4-
EMPTY_OK = Flows::Result::Ok.new(nil).freeze
5-
EMPTY_ERR = Flows::Result::Err.new(nil).freeze
4+
EMPTY_OK = Flows::Result::Ok.new({}.freeze).freeze
5+
EMPTY_ERR = Flows::Result::Err.new({}.freeze).freeze
66

77
# @api private
88
class MutationStep < Step
9-
NODE_PREPROCESSOR = lambda do |_input, context, meta|
10-
context[:last_step] = meta[:name]
11-
9+
NODE_PREPROCESSOR = lambda do |_input, context, node_meta|
1210
context[:class].before_each_callbacks.each do |callback|
13-
callback.call(context[:class], meta[:name], context[:data])
11+
callback.call(context[:class], node_meta[:name], context[:data], context[:meta])
1412
end
1513

1614
[[context[:data]], EMPTY_HASH]
1715
end
1816

19-
NODE_POSTPROCESSOR = lambda do |output, context, meta|
17+
NODE_POSTPROCESSOR = lambda do |output, context, node_meta|
2018
case output
2119
when Flows::Result then output
2220
else output ? EMPTY_OK : EMPTY_ERR
2321
end.tap do |result|
2422
context[:class].after_each_callbacks.each do |callback|
25-
callback.call(context[:class], meta[:name], context[:data], result)
23+
callback.call(context[:class], node_meta[:name], result, context[:data], context[:meta])
2624
end
2725
end
2826
end

lib/flows/shared_context_pipeline/step.rb

+6-8
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,9 @@ def to_node(pipeline_class)
1919

2020
Step.const_set(
2121
:NODE_PREPROCESSOR,
22-
lambda do |_input, context, meta|
23-
context[:last_step] = meta[:name]
24-
22+
lambda do |_input, context, node_meta|
2523
context[:class].before_each_callbacks.each do |callback|
26-
callback.call(context[:class], meta[:name], context[:data])
24+
callback.call(context[:class], node_meta[:name], context[:data], context[:meta])
2725
end
2826

2927
[EMPTY_ARRAY, context[:data]]
@@ -32,14 +30,14 @@ def to_node(pipeline_class)
3230

3331
Step.const_set(
3432
:NODE_POSTPROCESSOR,
35-
lambda do |output, context, meta|
36-
context[:data].merge!(output.instance_variable_get(:@data))
33+
lambda do |result, context, node_meta|
34+
context[:data].merge!(result.instance_variable_get(:@data))
3735

3836
context[:class].after_each_callbacks.each do |callback|
39-
callback.call(context[:class], meta[:name], context[:data], output)
37+
callback.call(context[:class], node_meta[:name], result, context[:data], context[:meta])
4038
end
4139

42-
output
40+
result
4341
end
4442
)
4543
end

0 commit comments

Comments
 (0)