trailblazer-operation 0.1.3 → 0.2.0
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 +5 -5
- data/CHANGES.md +8 -0
- data/Gemfile +2 -2
- data/lib/trailblazer/operation.rb +42 -46
- data/lib/trailblazer/operation/deprecated_macro.rb +3 -3
- data/lib/trailblazer/operation/heritage.rb +30 -0
- data/lib/trailblazer/operation/inject.rb +3 -1
- data/lib/trailblazer/operation/inspect.rb +1 -2
- data/lib/trailblazer/operation/public_call.rb +3 -26
- data/lib/trailblazer/operation/railway/macaroni.rb +1 -1
- data/lib/trailblazer/operation/railway/normalizer.rb +37 -56
- data/lib/trailblazer/operation/railway/task_builder.rb +0 -1
- data/lib/trailblazer/operation/trace.rb +15 -11
- data/lib/trailblazer/operation/variable_mapping.rb +2 -2
- data/lib/trailblazer/operation/version.rb +1 -1
- data/test/docs/macaroni_test.rb +1 -1
- data/test/docs/wiring_test.rb +86 -0
- data/test/fast_track_test.rb +1 -1
- data/test/introspect_test.rb +1 -0
- data/test/ruby-2.0.0/operation_test.rb +0 -12
- data/test/task_wrap_test.rb +21 -15
- data/test/trace_test.rb +3 -2
- data/test/variable_mapping_test.rb +19 -12
- data/test/wiring/defaults_test.rb +1 -1
- data/trailblazer-operation.gemspec +1 -1
- metadata +8 -8
- data/lib/trailblazer/operation/task_wrap.rb +0 -68
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: aa73a58eaa839d57774f73fe429398d0902e0e60e1bc3544f47762a773708140
|
4
|
+
data.tar.gz: b6ceaf6448980129f728fcbad8914558d4556517c20f0a65ff1bbcfa4f70340b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6d98db1f3a941c4547f0145148c3675c7892f535cbd90f7f30d722abfdb8b657979f21c2d383f7d656e064619738a250341538eddf6fb0d8d066131cb75433de
|
7
|
+
data.tar.gz: dda3c25bc10b64892344f5cdbf9ae3329dc10354f41b8b9907a383714dda6542c8607bc278b04a1e039687045a32b3cf30c58a8f0a15298bc60339c13569bd90
|
data/CHANGES.md
CHANGED
@@ -14,6 +14,14 @@ lots of work on the DSL specific parts.
|
|
14
14
|
|
15
15
|
params:, rest: ..
|
16
16
|
|
17
|
+
## 0.2.0
|
18
|
+
|
19
|
+
* Cleanly separate `Activity` and `Operation` responsibilities. An operation is nothing more but a class around an activity, hosting instance methods and implementing inheritance.
|
20
|
+
|
21
|
+
## 0.1.4
|
22
|
+
|
23
|
+
* `TaskWrap.arguments_for_call` now returns the correct `circuit_options` where the `:runner` etc.'s already merged.
|
24
|
+
|
17
25
|
## 0.1.3
|
18
26
|
|
19
27
|
* New taskWrap API for `activity` 0.3.2.
|
data/Gemfile
CHANGED
@@ -13,12 +13,12 @@ gem "benchmark-ips"
|
|
13
13
|
# gem "trailblazer-circuit", git: "https://github.com/trailblazer/trailblazer-circuit"
|
14
14
|
# gem "trailblazer-activity", path: "../trailblazer-activity"
|
15
15
|
# gem "trailblazer-developer", path: "../developer"
|
16
|
-
gem "trailblazer-developer", git: "https://github.com/trailblazer/trailblazer-developer"
|
16
|
+
# gem "trailblazer-developer", git: "https://github.com/trailblazer/trailblazer-developer"
|
17
17
|
# gem "representable", path: "../representable"
|
18
18
|
|
19
19
|
# gem "raise", path: "../raise"
|
20
20
|
|
21
21
|
# gem "declarative", path: "../declarative"
|
22
22
|
|
23
|
-
gem "trailblazer-activity", path: "../
|
23
|
+
# gem "trailblazer-activity", path: "../circuit"
|
24
24
|
# gem "trailblazer-activity", git: "https://github.com/trailblazer/trailblazer-activity"
|
@@ -7,20 +7,19 @@ require "trailblazer/container_chain"
|
|
7
7
|
|
8
8
|
require "trailblazer/activity"
|
9
9
|
require "trailblazer/activity/magnetic"
|
10
|
-
|
10
|
+
|
11
11
|
|
12
12
|
require "trailblazer/operation/variable_mapping"
|
13
13
|
|
14
|
+
require "trailblazer/operation/heritage"
|
14
15
|
require "trailblazer/operation/public_call" # TODO: Remove in 3.0.
|
15
16
|
require "trailblazer/operation/skill"
|
16
17
|
require "trailblazer/operation/deprecated_macro" # TODO: remove in 2.2.
|
17
18
|
require "trailblazer/operation/result"
|
18
19
|
require "trailblazer/operation/railway"
|
19
20
|
|
20
|
-
require "trailblazer/operation/railway/task_builder"
|
21
21
|
require "trailblazer/operation/railway/fast_track"
|
22
22
|
require "trailblazer/operation/railway/normalizer"
|
23
|
-
require "trailblazer/operation/task_wrap"
|
24
23
|
require "trailblazer/operation/trace"
|
25
24
|
|
26
25
|
require "trailblazer/operation/railway/macaroni"
|
@@ -29,6 +28,18 @@ module Trailblazer
|
|
29
28
|
# The Trailblazer-style operation.
|
30
29
|
# Note that you don't have to use our "opinionated" version with result object, skills, etc.
|
31
30
|
class Operation
|
31
|
+
|
32
|
+
module FastTrackActivity
|
33
|
+
builder_options = {
|
34
|
+
track_end: Railway::End::Success.new(:success, semantic: :success),
|
35
|
+
failure_end: Railway::End::Failure.new(:failure, semantic: :failure),
|
36
|
+
pass_fast_end: Railway::End::PassFast.new(:pass_fast, semantic: :pass_fast),
|
37
|
+
fail_fast_end: Railway::End::FailFast.new(:fail_fast, semantic: :fail_fast),
|
38
|
+
}
|
39
|
+
|
40
|
+
extend Activity::FastTrack( pipeline: Railway::Normalizer::Pipeline, builder_options: builder_options )
|
41
|
+
end
|
42
|
+
|
32
43
|
extend Skill::Accessors # ::[] and ::[]= # TODO: fade out this usage.
|
33
44
|
|
34
45
|
def self.inherited(subclass)
|
@@ -37,69 +48,54 @@ module Trailblazer
|
|
37
48
|
heritage.(subclass)
|
38
49
|
end
|
39
50
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
recompile_process!
|
44
|
-
end
|
45
|
-
|
46
|
-
# builder is stateless, it's up to you to save @adds somewhere.
|
47
|
-
def initialize_activity_dsl!
|
48
|
-
builder_options = {
|
49
|
-
track_end: Railway::End::Success.new(:success, semantic: :success),
|
50
|
-
failure_end: Railway::End::Failure.new(:failure, semantic: :failure),
|
51
|
-
pass_fast_end: Railway::End::PassFast.new(:pass_fast, semantic: :pass_fast),
|
52
|
-
fail_fast_end: Railway::End::FailFast.new(:fail_fast, semantic: :fail_fast),
|
53
|
-
}
|
54
|
-
|
55
|
-
@builder, @adds = Activity::Magnetic::Builder::FastTrack.for( build_normalizer.freeze, builder_options )
|
56
|
-
@debug = {}
|
57
|
-
end
|
58
|
-
|
59
|
-
def recompile_process!
|
60
|
-
@process, @outputs = Activity::Recompile.( @adds )
|
61
|
-
end
|
51
|
+
def self.initialize!
|
52
|
+
@activity = FastTrackActivity.clone
|
53
|
+
end
|
62
54
|
|
63
|
-
def outputs
|
64
|
-
@outputs
|
65
|
-
end
|
66
55
|
|
67
|
-
|
56
|
+
extend Activity::Interface
|
68
57
|
|
58
|
+
module Process
|
69
59
|
# Call the actual {Process} with the options prepared in PublicCall.
|
70
|
-
|
71
|
-
|
60
|
+
#
|
61
|
+
# @private
|
62
|
+
def __call__(args, argumenter: [], **circuit_options)
|
63
|
+
@activity.( args, circuit_options.merge(
|
64
|
+
exec_context: new,
|
65
|
+
argumenter: argumenter + [ Activity::TaskWrap.method(:arguments_for_call) ], # FIXME: should we move this outside?
|
66
|
+
)
|
67
|
+
)
|
72
68
|
end
|
73
69
|
|
74
|
-
|
75
|
-
|
76
|
-
def build_normalizer
|
77
|
-
Railway::Normalizer.new
|
70
|
+
def decompose
|
71
|
+
@activity.decompose.merge( activity: @activity )
|
78
72
|
end
|
79
73
|
end
|
80
74
|
|
81
75
|
extend Process # make ::call etc. class methods on Operation.
|
82
76
|
|
83
|
-
extend
|
77
|
+
extend Heritage::Accessor
|
84
78
|
|
85
|
-
extend Activity::DSL # #_task
|
86
|
-
# delegate step, pass and fail via Operation::_task to the @builder, and save results in @adds.
|
87
|
-
extend Activity::DSL.def_dsl! :step
|
88
|
-
extend Activity::DSL.def_dsl! :pass
|
89
|
-
extend Activity::DSL.def_dsl! :fail
|
90
79
|
class << self
|
80
|
+
extend Forwardable # TODO: test those helpers
|
81
|
+
def_delegators :@activity, :Path, :Output, :End
|
82
|
+
def_delegators :@activity, :outputs, :debug
|
83
|
+
|
84
|
+
def step(task, options={}, &block); add_task!(:step, task, options, &block) end
|
85
|
+
def pass(task, options={}, &block); add_task!(:pass, task, options, &block) end
|
86
|
+
def fail(task, options={}, &block); add_task!(:fail, task, options, &block) end
|
87
|
+
|
91
88
|
alias_method :success, :pass
|
92
89
|
alias_method :failure, :fail
|
93
90
|
|
94
|
-
|
95
|
-
|
91
|
+
def add_task!(name, task, options, &block)
|
92
|
+
heritage.record(name, task, options, &block)
|
93
|
+
@activity.send(name, task, options, &block)
|
94
|
+
end
|
96
95
|
end
|
97
96
|
|
98
97
|
extend PublicCall # ::call(params, { current_user: .. })
|
99
98
|
extend Trace # ::trace
|
100
|
-
|
101
|
-
|
102
|
-
include Railway::TaskWrap
|
103
99
|
end
|
104
100
|
end
|
105
101
|
|
@@ -2,18 +2,18 @@
|
|
2
2
|
module Trailblazer
|
3
3
|
module Operation::DeprecatedMacro
|
4
4
|
# Allows old macros with the `(input, options)` signature.
|
5
|
-
def self.call(proc, options
|
5
|
+
def self.call(proc, options)
|
6
6
|
warn %{[Trailblazer] Macros with API (input, options) are deprecated. Please use the "Task API" signature (options, flow_options) or use a simpler Callable. (#{proc})}
|
7
7
|
|
8
8
|
wrapped_proc = ->( (options, flow_options), **circuit_options ) do
|
9
9
|
result = proc.(circuit_options[:exec_context], options) # run the macro, with the deprecated signature.
|
10
10
|
|
11
|
-
direction =
|
11
|
+
direction = Activity::TaskBuilder::Binary.binary_direction_for(result, Activity::Right, Activity::Left)
|
12
12
|
|
13
13
|
return direction, [options, flow_options]
|
14
14
|
end
|
15
15
|
|
16
|
-
|
16
|
+
options.merge( task: wrapped_proc )
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Trailblazer
|
2
|
+
# This is copied from the Declarative gem. This might get removed in favor of a real heritage gem.
|
3
|
+
class Operation
|
4
|
+
class Heritage < Array
|
5
|
+
# Record inheritable assignments for replay in an inheriting class.
|
6
|
+
def record(method, *args, &block)
|
7
|
+
self << { method: method, args: args, block: block }
|
8
|
+
end
|
9
|
+
|
10
|
+
# Replay the recorded assignments on inheritor.
|
11
|
+
# Accepts a block that will allow processing the arguments for every recorded statement.
|
12
|
+
def call(inheritor, &block)
|
13
|
+
each { |cfg| call!(inheritor, cfg, &block) }
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
def call!(inheritor, cfg)
|
18
|
+
yield cfg if block_given? # allow messing around with recorded arguments.
|
19
|
+
|
20
|
+
inheritor.send(cfg[:method], *cfg[:args], &cfg[:block])
|
21
|
+
end
|
22
|
+
|
23
|
+
module Accessor
|
24
|
+
def heritage
|
25
|
+
@heritage ||= Heritage.new
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -6,7 +6,9 @@ module Trailblazer
|
|
6
6
|
# injection but need a default parameter to be set if not injected.
|
7
7
|
# @returns ADDS
|
8
8
|
def self.Defaults(default_dependencies)
|
9
|
-
|
9
|
+
Module.new do
|
10
|
+
extend Activity::Path::Plan()
|
11
|
+
|
10
12
|
task ReverseMergeDefaults.new( default_dependencies ),
|
11
13
|
id: "ReverseMergeDefaults#{default_dependencies}",
|
12
14
|
before: "task_wrap.call_task"
|
@@ -17,8 +17,7 @@ module Trailblazer
|
|
17
17
|
def call(operation, options={ style: :line })
|
18
18
|
# TODO: better introspection API.
|
19
19
|
|
20
|
-
|
21
|
-
alterations = Activity::Magnetic::Builder::Finalizer.adds_to_alterations(adds)
|
20
|
+
alterations = Activity::Magnetic::Builder::Finalizer.adds_to_alterations(operation.decompose[:adds])
|
22
21
|
# DISCUSS: any other way to retrieve the Alterations?
|
23
22
|
|
24
23
|
# pp alterations
|
@@ -10,6 +10,8 @@ class Trailblazer::Operation
|
|
10
10
|
# In workflows/Nested compositions, this method is not used anymore and it might probably
|
11
11
|
# get removed in future versions of TRB. Currently, we use Operation::__call__ as an alternative.
|
12
12
|
#
|
13
|
+
#
|
14
|
+
# @note Do not override this method as it will be removed in future versions. Also, you will break tracing.
|
13
15
|
# @return Operation::Railway::Result binary result object
|
14
16
|
def call(*args)
|
15
17
|
ctx = PublicCall.options_for_public_call(*args)
|
@@ -21,11 +23,9 @@ class Trailblazer::Operation
|
|
21
23
|
Railway::Result(last_signal, options, flow_options)
|
22
24
|
end
|
23
25
|
|
24
|
-
private
|
25
26
|
# Compile a Context object to be passed into the Activity::call.
|
27
|
+
# @private
|
26
28
|
def self.options_for_public_call(options={}, *containers)
|
27
|
-
# options, *containers = Deprecations.accept_positional_options(params, options, *containers) # TODO: make this optional for "power users".
|
28
|
-
|
29
29
|
# generate the skill hash that embraces runtime options plus potential containers, the so called Runtime options.
|
30
30
|
# This wrapping is supposed to happen once in the entire system.
|
31
31
|
|
@@ -35,28 +35,5 @@ class Trailblazer::Operation
|
|
35
35
|
|
36
36
|
ctx = Trailblazer::Context(immutable_options)
|
37
37
|
end
|
38
|
-
|
39
|
-
module Deprecations
|
40
|
-
# Merge the first argument to the public Create.() into the second.
|
41
|
-
#
|
42
|
-
# DISCUSS: this is experimental since we can never know whether the call is the old or new API.
|
43
|
-
#
|
44
|
-
# The following situations are _not_ covered here:
|
45
|
-
# * You're using a Hash instance as a container.
|
46
|
-
# * You're using more than one container.
|
47
|
-
#
|
48
|
-
# If you do so (we're assuming you know what you're doing then), please update your `call`s.
|
49
|
-
def self.accept_positional_options( *args )
|
50
|
-
if args.size == 1 && args[0].instance_of?(Hash) # new style, you're doing it right.
|
51
|
-
args
|
52
|
-
elsif args.size == 2 && args[0].instance_of?(Hash) && !args[1].instance_of?(Hash) # new style with container, you're doing it right.
|
53
|
-
args
|
54
|
-
else
|
55
|
-
warn "[Trailblazer] Passing two positional arguments to `Operation.( params, current_user: .. )` is deprecated. Please use one hash like `Operation.( params: params, current_user: .. )`"
|
56
|
-
params, options, *containers = args
|
57
|
-
[ options.merge("params" => params), *containers ]
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
38
|
end
|
62
39
|
end
|
@@ -7,7 +7,7 @@ module Trailblazer
|
|
7
7
|
# def my_step( params:, options:, ** )
|
8
8
|
module Macaroni
|
9
9
|
def self.call(user_proc)
|
10
|
-
Task.new( Trailblazer::Option.build( Macaroni::Option, user_proc ), user_proc )
|
10
|
+
Activity::TaskBuilder::Task.new( Trailblazer::Option.build( Macaroni::Option, user_proc ), user_proc )
|
11
11
|
end
|
12
12
|
|
13
13
|
class Option < Trailblazer::Option
|
@@ -5,73 +5,54 @@ module Trailblazer
|
|
5
5
|
# task via {TaskBuilder} in order to translate true/false to `Right` or `Left`.
|
6
6
|
#
|
7
7
|
# The Normalizer sits in the `@builder`, which receives all DSL calls from the Operation subclass.
|
8
|
-
|
9
|
-
|
10
|
-
@task_builder = task_builder
|
11
|
-
end
|
12
|
-
|
13
|
-
def call(task, options, unknown_options, sequence_options)
|
14
|
-
wrapped_task, options =
|
15
|
-
if task.is_a?(::Hash) # macro.
|
16
|
-
[
|
17
|
-
task[:task],
|
18
|
-
task.merge(options) # Note that the user options are merged over the macro options.
|
19
|
-
]
|
20
|
-
elsif task.is_a?(Array) # TODO remove in 2.2
|
21
|
-
Operation::DeprecatedMacro.( *task )
|
22
|
-
else # user step
|
23
|
-
[
|
24
|
-
@task_builder.(task),
|
25
|
-
{ id: task }.merge(options) # default :id
|
26
|
-
]
|
27
|
-
end
|
28
|
-
|
29
|
-
options, unknown_options = deprecate_name(options, unknown_options) # TODO remove in 2.2
|
8
|
+
module Normalizer
|
9
|
+
Pipeline = Activity::Magnetic::Normalizer::Pipeline.clone
|
30
10
|
|
31
|
-
|
11
|
+
Pipeline.module_eval do
|
12
|
+
# Handle the :override option which is specific to Operation.
|
13
|
+
def self.override(ctx, task:, options:, sequence_options:, **)
|
14
|
+
options, locals = Activity::Magnetic::Options.normalize(options, [:override])
|
15
|
+
sequence_options = sequence_options.merge( replace: options[:id] ) if locals[:override]
|
32
16
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
options, locals, sequence_options = override(task, options, sequence_options) # :override
|
17
|
+
ctx[:options], ctx[:sequence_options] = options, sequence_options
|
18
|
+
end
|
37
19
|
|
38
|
-
|
39
|
-
|
20
|
+
# TODO remove in 2.2
|
21
|
+
def self.deprecate_macro_with_two_args(ctx, task:, **)
|
22
|
+
return true unless task.is_a?(Array) # TODO remove in 2.2
|
40
23
|
|
41
|
-
|
42
|
-
|
43
|
-
{
|
44
|
-
plus_poles: InitialPlusPoles(),
|
45
|
-
}.merge(options)
|
46
|
-
end
|
24
|
+
ctx[:options] = Operation::DeprecatedMacro.( *task )
|
25
|
+
end
|
47
26
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
27
|
+
# TODO remove in 2.2
|
28
|
+
def self.deprecate_name(ctx, local_options:, connection_options:, **)
|
29
|
+
connection_options, deprecated_options = Activity::Magnetic::Options.normalize(connection_options, [:name])
|
30
|
+
local_options, _deprecated_options = Activity::Magnetic::Options.normalize(local_options, [:name])
|
52
31
|
|
53
|
-
|
54
|
-
end
|
32
|
+
deprecated_options = deprecated_options.merge(_deprecated_options)
|
55
33
|
|
56
|
-
|
57
|
-
Activity::Magnetic::DSL::PlusPoles.new.merge(
|
58
|
-
Activity.Output(Activity::Right, :success) => nil,
|
59
|
-
Activity.Output(Activity::Left, :failure) => nil,
|
60
|
-
)
|
61
|
-
end
|
34
|
+
local_options = local_options.merge( name: deprecated_options[:name] ) if deprecated_options[:name]
|
62
35
|
|
63
|
-
|
64
|
-
|
36
|
+
local_options, locals = Activity::Magnetic::Options.normalize(local_options, [:name])
|
37
|
+
if locals[:name]
|
38
|
+
warn "[Trailblazer] The :name option for #step, #success and #failure has been renamed to :id."
|
39
|
+
local_options = local_options.merge(id: locals[:name])
|
40
|
+
end
|
65
41
|
|
66
|
-
|
42
|
+
ctx[:local_options], ctx[:connection_options] = local_options, connection_options
|
43
|
+
end
|
67
44
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
options = options.merge(id: locals[:name])
|
45
|
+
def self.raise_on_missing_id(ctx, local_options:, **)
|
46
|
+
raise "No :id given for #{local_options[:task]}" unless local_options[:id]
|
47
|
+
true
|
72
48
|
end
|
73
|
-
|
49
|
+
|
50
|
+
# add more normalization tasks to the existing Magnetic::Normalizer::Pipeline
|
51
|
+
task Activity::TaskBuilder::Binary.( method(:deprecate_macro_with_two_args) ), before: "split_options"
|
52
|
+
task Activity::TaskBuilder::Binary.( method(:deprecate_name) )
|
53
|
+
task Activity::TaskBuilder::Binary.( method(:override) )
|
54
|
+
task Activity::TaskBuilder::Binary.( method(:raise_on_missing_id) )
|
74
55
|
end
|
75
|
-
end
|
56
|
+
end # Normalizer
|
76
57
|
end
|
77
58
|
end
|
@@ -1,21 +1,25 @@
|
|
1
1
|
module Trailblazer
|
2
2
|
class Operation
|
3
3
|
module Trace
|
4
|
+
# @note The problem in this method is, we have redundancy with Operation::PublicCall
|
4
5
|
def self.call(operation, *args)
|
5
|
-
ctx = PublicCall.
|
6
|
+
ctx = PublicCall.options_for_public_call(*args) # redundant with PublicCall::call.
|
6
7
|
|
7
|
-
#
|
8
|
-
|
8
|
+
# Prepare the tracing-specific arguments. This is only run once for the entire circuit!
|
9
|
+
operation, (options, flow_options), circuit_options = Trailblazer::Activity::Trace.arguments_for_call( operation, [ctx, {}], {} )
|
9
10
|
|
10
|
-
|
11
|
-
operation,
|
12
|
-
ctx,
|
13
|
-
&call_block # instructs Trace to use __call__.
|
14
|
-
)
|
11
|
+
circuit_options = circuit_options.merge({ argumenter: [ Trailblazer::Activity::Introspect.method(:arguments_for_call) ] }) # this is called for every Activity.
|
15
12
|
|
16
|
-
result = Railway::Result(direction, options)
|
17
13
|
|
18
|
-
|
14
|
+
last_signal, (options, flow_options) =
|
15
|
+
operation.__call__( # FIXME: this is the only problem.
|
16
|
+
[options, flow_options],
|
17
|
+
circuit_options
|
18
|
+
)
|
19
|
+
|
20
|
+
result = Railway::Result(last_signal, options) # redundant with PublicCall::call.
|
21
|
+
|
22
|
+
Result.new(result, flow_options[:stack].to_a)
|
19
23
|
end
|
20
24
|
|
21
25
|
# `Operation::trace` is included for simple tracing of the flow.
|
@@ -37,7 +41,7 @@ module Trailblazer
|
|
37
41
|
end
|
38
42
|
|
39
43
|
def wtf
|
40
|
-
Activity::Trace::Present.tree(@stack)
|
44
|
+
Trailblazer::Activity::Trace::Present.tree(@stack)
|
41
45
|
end
|
42
46
|
|
43
47
|
def wtf?
|
data/test/docs/macaroni_test.rb
CHANGED
@@ -10,7 +10,7 @@ class MacaroniTaskBuilderTest < Minitest::Spec
|
|
10
10
|
#:create
|
11
11
|
class Memo::Create < Trailblazer::Operation
|
12
12
|
#~ign
|
13
|
-
Normalizer =
|
13
|
+
Normalizer, _ = Trailblazer::Activity::Magnetic::Normalizer.build( task_builder: Railway::KwSignature, pipeline: Railway::Normalizer::Pipeline )
|
14
14
|
|
15
15
|
step :create_model, normalizer: Normalizer
|
16
16
|
step :save, normalizer: Normalizer
|
data/test/docs/wiring_test.rb
CHANGED
@@ -471,3 +471,89 @@ class WiringsDocCustomConnectionTest < Minitest::Spec
|
|
471
471
|
result.inspect(:new?, :upload, :validate, :validation_error, :index).must_equal %{<Result:false [true, true, false, true, nil] >}
|
472
472
|
end
|
473
473
|
end
|
474
|
+
|
475
|
+
class WiringsDocDeciderTest < Minitest::Spec
|
476
|
+
Memo = Class.new(WiringDocsTest::Memo)
|
477
|
+
|
478
|
+
#:decider
|
479
|
+
class Memo::Upsert < Trailblazer::Operation
|
480
|
+
step :find_model, Output(:failure) => :create_route
|
481
|
+
step :update
|
482
|
+
step :create, magnetic_to: [:create_route]
|
483
|
+
step :save
|
484
|
+
#~decm
|
485
|
+
def find_model(options, id:nil, **)
|
486
|
+
options[:model] = Memo.find(id)
|
487
|
+
end
|
488
|
+
|
489
|
+
def find_model(options, id:, **)
|
490
|
+
options[:find_model] = id
|
491
|
+
end
|
492
|
+
def update(options, **)
|
493
|
+
options[:update] = true
|
494
|
+
end
|
495
|
+
def create(options, **)
|
496
|
+
options[:create] = true
|
497
|
+
end
|
498
|
+
def save(options, **)
|
499
|
+
options[:save] = true
|
500
|
+
end
|
501
|
+
#~decm end
|
502
|
+
end
|
503
|
+
#:decider end
|
504
|
+
|
505
|
+
it "goes the create route" do
|
506
|
+
Memo::Upsert.( id: false ).inspect(:find_model, :update, :create, :save).must_equal %{<Result:true [false, nil, true, true] >}
|
507
|
+
end
|
508
|
+
|
509
|
+
it "goes the update route" do
|
510
|
+
Memo::Upsert.( id: true ).inspect(:find_model, :update, :create, :save).must_equal %{<Result:true [true, true, nil, true] >}
|
511
|
+
end
|
512
|
+
end
|
513
|
+
|
514
|
+
class WiringsDocEndTest < Minitest::Spec
|
515
|
+
Memo = Class.new(WiringDocsTest::Memo)
|
516
|
+
|
517
|
+
#:end
|
518
|
+
class Memo::Update < Trailblazer::Operation
|
519
|
+
step :find_model, Output(:failure) => End("End.model_not_found", :model_not_found)
|
520
|
+
step :update
|
521
|
+
fail :db_error
|
522
|
+
step :save
|
523
|
+
#~methods
|
524
|
+
def find_model(options, id:nil, **)
|
525
|
+
options[:model] = Memo.find(id)
|
526
|
+
end
|
527
|
+
|
528
|
+
def find_model(options, id:, **)
|
529
|
+
options[:find_model] = id
|
530
|
+
end
|
531
|
+
def update(options, update: true, **)
|
532
|
+
options[:update] = update
|
533
|
+
end
|
534
|
+
def db_error(options, **)
|
535
|
+
options[:db_error] = 1
|
536
|
+
end
|
537
|
+
def save(options, **)
|
538
|
+
options[:save] = true
|
539
|
+
end
|
540
|
+
#~methods end
|
541
|
+
end
|
542
|
+
#:end end
|
543
|
+
|
544
|
+
it "goes success path" do
|
545
|
+
Memo::Update.( id: true ).inspect(:find_model, :update, :save, :db_error).must_equal %{<Result:true [true, true, true, nil] >}
|
546
|
+
end
|
547
|
+
|
548
|
+
it "errors out on End.model_not_found" do
|
549
|
+
result = Memo::Update.( id: false )
|
550
|
+
result.inspect(:find_model, :update, :save, :db_error).must_equal %{<Result:false [false, nil, nil, nil] >}
|
551
|
+
result.event.instance_variable_get(:@options).must_equal(semantic: :model_not_found)
|
552
|
+
end
|
553
|
+
|
554
|
+
it "takes normal error track" do
|
555
|
+
result = Memo::Update.( id: true, update: false )
|
556
|
+
result.inspect(:find_model, :update, :save, :db_error).must_equal %{<Result:false [true, false, nil, 1] >}
|
557
|
+
result.event.instance_variable_get(:@options).must_equal(semantic: :failure)
|
558
|
+
end
|
559
|
+
end
|
data/test/fast_track_test.rb
CHANGED
@@ -183,7 +183,7 @@ class NestedFastTrackTest < Minitest::Spec
|
|
183
183
|
end
|
184
184
|
|
185
185
|
# it { puts Trailblazer::Activity::Introspect.Cct(update.instance_variable_get(:@process)) }
|
186
|
-
it {
|
186
|
+
it { update.decompose[0] }
|
187
187
|
# Edit returns End.success
|
188
188
|
it { update.(edit_return: true).inspect("a", "b", "f").must_equal %{<Result:true [1, 2, nil] >} }
|
189
189
|
# Edit returns End.failure
|
data/test/introspect_test.rb
CHANGED
@@ -59,15 +59,3 @@ class DeclarativeApiTest < Minitest::Spec
|
|
59
59
|
it { Update.(decide: true).inspect("a", "b", "c").must_equal %{<Result:true [false, true, nil] >} }
|
60
60
|
it { Update.(decide: false).inspect("a", "b", "c").must_equal %{<Result:false [false, false, true] >} }
|
61
61
|
end
|
62
|
-
|
63
|
-
|
64
|
-
=begin
|
65
|
-
module MiniTest::Assertions
|
66
|
-
def assert_inspect(text, subject)
|
67
|
-
circuit, _ = subject.values
|
68
|
-
map, _ = circuit.to_fields
|
69
|
-
map.inspect.gsub(/0x.+?lambda\)/, "").gsub("Trailblazer::Circuit::", "").gsub("AlterTest::", "").must_equal(text)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
Trailblazer::Circuit::Activity.infect_an_assertion :assert_inspect, :must_inspect
|
73
|
-
=end
|
data/test/task_wrap_test.rb
CHANGED
@@ -15,14 +15,17 @@ class TaskWrapTest < Minitest::Spec
|
|
15
15
|
task: MyMacro,
|
16
16
|
id: "MyMacro",
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
18
|
+
extension: [
|
19
|
+
Trailblazer::Activity::TaskWrap::Merge.new(
|
20
|
+
Module.new do
|
21
|
+
extend Trailblazer::Activity::Path::Plan()
|
22
|
+
|
23
|
+
task Trailblazer::Operation::Wrap::Inject::ReverseMergeDefaults.new( contract: "MyDefaultContract" ),
|
24
|
+
id: "inject.my_default",
|
25
|
+
before: "task_wrap.call_task"
|
26
|
+
end
|
27
|
+
)
|
28
|
+
]
|
26
29
|
)
|
27
30
|
|
28
31
|
def model!(options, **)
|
@@ -42,7 +45,6 @@ class TaskWrapTest < Minitest::Spec
|
|
42
45
|
it do
|
43
46
|
direction, (options, _) = Create.__call__( [{}, {}] )
|
44
47
|
|
45
|
-
|
46
48
|
inspect_hash(options, "options.contract", :contract, "MyMacro.contract").
|
47
49
|
must_equal %{{"options.contract"=>nil, :contract=>"MyDefaultContract", "MyMacro.contract"=>"MyDefaultContract"}}
|
48
50
|
end
|
@@ -73,12 +75,16 @@ class TaskWrapTest < Minitest::Spec
|
|
73
75
|
step(
|
74
76
|
task: AnotherMacro,
|
75
77
|
id: "AnotherMacro",
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
78
|
+
extension: [
|
79
|
+
Trailblazer::Activity::TaskWrap::Merge.new(
|
80
|
+
Module.new do
|
81
|
+
extend Trailblazer::Activity::Path::Plan()
|
82
|
+
|
83
|
+
task Trailblazer::Operation::Wrap::Inject::ReverseMergeDefaults.new( another_contract: "AnotherDefaultContract" ), id: "inject.my_default",
|
84
|
+
before: "task_wrap.call_task"
|
85
|
+
end
|
86
|
+
)
|
87
|
+
]
|
82
88
|
)
|
83
89
|
end
|
84
90
|
|
data/test/trace_test.rb
CHANGED
@@ -28,7 +28,8 @@ class TraceTest < Minitest::Spec
|
|
28
28
|
stack, _ = Trailblazer::Activity::Trace.(
|
29
29
|
Create,
|
30
30
|
[
|
31
|
-
{ a_return: true,
|
31
|
+
{ a_return: true, params: {} },
|
32
|
+
{}
|
32
33
|
]
|
33
34
|
)
|
34
35
|
|
@@ -47,7 +48,7 @@ class TraceTest < Minitest::Spec
|
|
47
48
|
end
|
48
49
|
|
49
50
|
it "Operation::trace" do
|
50
|
-
result = Create.trace({
|
51
|
+
result = Create.trace({ params: { x: 1 }, a_return: true })
|
51
52
|
result.wtf.gsub(/0x\w+/, "").gsub(/@.+_test/, "").must_equal %{|-- #<Trailblazer::Activity::Start:>
|
52
53
|
|-- Create.task.a
|
53
54
|
|-- MyNested
|
@@ -20,9 +20,11 @@ class VariableMappingTest < Minitest::Spec
|
|
20
20
|
end
|
21
21
|
|
22
22
|
let (:activity) do
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
Module.new do
|
24
|
+
extend Activity::Path()
|
25
|
+
|
26
|
+
task task: Model
|
27
|
+
task task: Uuid
|
26
28
|
end
|
27
29
|
end
|
28
30
|
|
@@ -34,18 +36,22 @@ class VariableMappingTest < Minitest::Spec
|
|
34
36
|
uuid_input = ->(options) { { "a" => options["a"]*3, "model.a" => options["model.a"] } }
|
35
37
|
uuid_output = ->(options) { { "uuid.a" => options["a"] } }
|
36
38
|
|
37
|
-
runtime =
|
39
|
+
runtime = {}
|
38
40
|
|
39
41
|
# add filters around Model.
|
40
|
-
runtime[ Model ] =
|
41
|
-
|
42
|
-
|
42
|
+
runtime[ Model ] = Module.new do
|
43
|
+
extend Activity::Path::Plan()
|
44
|
+
|
45
|
+
task Activity::TaskWrap::Input.new( model_input ), id: "task_wrap.input", before: "task_wrap.call_task"
|
46
|
+
task Activity::TaskWrap::Output.new( model_output ), id: "task_wrap.output", before: "End.success", group: :end
|
43
47
|
end
|
44
48
|
|
45
49
|
# add filters around Uuid.
|
46
|
-
runtime[ Uuid ] =
|
47
|
-
|
48
|
-
|
50
|
+
runtime[ Uuid ] = Module.new do
|
51
|
+
extend Activity::Path::Plan()
|
52
|
+
|
53
|
+
task Activity::TaskWrap::Input.new( uuid_input ), id: "task_wrap.input", before: "task_wrap.call_task"
|
54
|
+
task Activity::TaskWrap::Output.new( uuid_output ), id: "task_wrap.output", before: "End.success", group: :end
|
49
55
|
end
|
50
56
|
|
51
57
|
signal, (options, flow_options) = activity.(
|
@@ -55,8 +61,9 @@ class VariableMappingTest < Minitest::Spec
|
|
55
61
|
],
|
56
62
|
|
57
63
|
wrap_runtime: runtime, # dynamic additions from the outside (e.g. tracing), also per task.
|
58
|
-
runner: Activity::
|
59
|
-
|
64
|
+
runner: Activity::TaskWrap::Runner,
|
65
|
+
argumenters: [ Activity::TaskWrap::NonStatic.method(:arguments_for_call) ],
|
66
|
+
wrap_static: Hash.new( Activity::TaskWrap.initial_activity ),
|
60
67
|
)
|
61
68
|
|
62
69
|
signal.must_equal activity.outputs[:success].signal
|
@@ -158,7 +158,7 @@ class WireDefaultsEarlyExitSuccessTest < Minitest::Spec
|
|
158
158
|
end
|
159
159
|
end
|
160
160
|
|
161
|
-
it { puts Trailblazer::Activity::Magnetic::Introspect.seq( Connect ) }
|
161
|
+
# it { puts Trailblazer::Activity::Magnetic::Introspect.seq( Connect.decompose.first ) }
|
162
162
|
|
163
163
|
# a => true
|
164
164
|
it { Connect.( a_return: true, b_return: true,data: []).inspect(:data).must_equal %{<Result:true [[:a, :b, :d]] >} }
|
@@ -17,7 +17,7 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
18
|
spec.require_paths = ["lib"]
|
19
19
|
|
20
|
-
spec.add_dependency "trailblazer-activity", ">= 0.
|
20
|
+
spec.add_dependency "trailblazer-activity", ">= 0.4.0", "< 0.5.0"
|
21
21
|
spec.add_dependency "trailblazer-context", ">= 0.1.1", "< 0.3.0"
|
22
22
|
|
23
23
|
spec.add_development_dependency "bundler"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trailblazer-operation
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Sutterer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-01-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: trailblazer-activity
|
@@ -16,20 +16,20 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.4.0
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: 0.
|
22
|
+
version: 0.5.0
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
27
|
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: 0.
|
29
|
+
version: 0.4.0
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: 0.
|
32
|
+
version: 0.5.0
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: trailblazer-context
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -107,6 +107,7 @@ files:
|
|
107
107
|
- Rakefile
|
108
108
|
- lib/trailblazer/operation.rb
|
109
109
|
- lib/trailblazer/operation/deprecated_macro.rb
|
110
|
+
- lib/trailblazer/operation/heritage.rb
|
110
111
|
- lib/trailblazer/operation/inject.rb
|
111
112
|
- lib/trailblazer/operation/inspect.rb
|
112
113
|
- lib/trailblazer/operation/public_call.rb
|
@@ -117,7 +118,6 @@ files:
|
|
117
118
|
- lib/trailblazer/operation/railway/task_builder.rb
|
118
119
|
- lib/trailblazer/operation/result.rb
|
119
120
|
- lib/trailblazer/operation/skill.rb
|
120
|
-
- lib/trailblazer/operation/task_wrap.rb
|
121
121
|
- lib/trailblazer/operation/trace.rb
|
122
122
|
- lib/trailblazer/operation/variable_mapping.rb
|
123
123
|
- lib/trailblazer/operation/version.rb
|
@@ -171,7 +171,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
171
171
|
version: '0'
|
172
172
|
requirements: []
|
173
173
|
rubyforge_project:
|
174
|
-
rubygems_version: 2.
|
174
|
+
rubygems_version: 2.7.3
|
175
175
|
signing_key:
|
176
176
|
specification_version: 4
|
177
177
|
summary: Trailblazer's operation object with railway flow and integrated error handling.
|
@@ -1,68 +0,0 @@
|
|
1
|
-
module Trailblazer
|
2
|
-
module Operation::Railway
|
3
|
-
module TaskWrap
|
4
|
-
def self.included(includer)
|
5
|
-
includer.extend ClassMethods # ::__call__, ::inititalize_task_wraps!
|
6
|
-
includer.extend DSL
|
7
|
-
|
8
|
-
includer.initialize_task_wraps!
|
9
|
-
end
|
10
|
-
|
11
|
-
module ClassMethods
|
12
|
-
def initialize_task_wraps!
|
13
|
-
heritage.record :initialize_task_wraps!
|
14
|
-
|
15
|
-
# The map of task_wrap per step/task. Note that it defaults to Wrap.initial_activity.
|
16
|
-
# This gets extended at compile-time for particular tasks as the steps are created via the DSL.
|
17
|
-
self["__static_task_wraps__"] = ::Hash.new(Activity::Wrap.initial_activity)
|
18
|
-
end
|
19
|
-
|
20
|
-
# __call__ prepares `flow_options` and `static_wraps` for {TaskWrap::Runner}.
|
21
|
-
def __call__(args, **circuit_args)
|
22
|
-
args, _circuit_args = TaskWrap.arguments_for_call(self, args, **circuit_args)
|
23
|
-
|
24
|
-
super( args, circuit_args.merge(_circuit_args) ) # Railway::__call__
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def self.arguments_for_call(operation, (options, flow_options), **circuit_args)
|
29
|
-
wrap_static = operation["__static_task_wraps__"]
|
30
|
-
|
31
|
-
circuit_args = {
|
32
|
-
runner: Activity::Wrap::Runner,
|
33
|
-
# FIXME: this sucks, why do we even need to pass an empty runtime there?
|
34
|
-
wrap_runtime: circuit_args[:wrap_runtime] || ::Hash.new([]), # FIXME:this sucks. (was:) this overwrites wrap_runtime from outside.
|
35
|
-
wrap_static: wrap_static,
|
36
|
-
}
|
37
|
-
|
38
|
-
return [ options, flow_options ], circuit_args
|
39
|
-
end
|
40
|
-
|
41
|
-
module DSL
|
42
|
-
# TODO: this override is hard to follow, we should have a pipeline circuit in DSL to add behavior.
|
43
|
-
# @private
|
44
|
-
def _task(*args)
|
45
|
-
returned = super # TODO: do this with a circuit :)
|
46
|
-
adds, (task, local_options) = returned
|
47
|
-
|
48
|
-
runner_options = local_options[:runner_options]
|
49
|
-
|
50
|
-
runner_options and apply_adds_from_runner_options!( task, runner_options )
|
51
|
-
|
52
|
-
returned
|
53
|
-
end
|
54
|
-
|
55
|
-
# Extend the static wrap for a specific task, at compile time.
|
56
|
-
def apply_adds_from_runner_options!(task, merge:raise, **ignored)
|
57
|
-
static_wrap = self["__static_task_wraps__"][task]
|
58
|
-
|
59
|
-
# macro might want to apply changes to the static task_wrap (e.g. Inject)
|
60
|
-
self["__static_task_wraps__"][task] = Activity::Magnetic::Builder.merge( static_wrap, merge )
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end # TaskWrap
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
|
68
|
-
# |-- Railway::Call "insert.exec_context"
|