trailblazer-operation 0.10.0 → 0.11.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 +4 -4
- data/.github/workflows/ci.yml +2 -2
- data/CHANGES.md +15 -0
- data/lib/trailblazer/operation/class_dependencies.rb +1 -1
- data/lib/trailblazer/operation/public_call.rb +24 -14
- data/lib/trailblazer/operation/railway.rb +13 -7
- data/lib/trailblazer/operation/version.rb +1 -1
- data/lib/trailblazer/operation/wtf.rb +11 -0
- data/lib/trailblazer/operation.rb +2 -2
- data/test/call_test.rb +32 -10
- data/test/class_dependencies_test.rb +8 -4
- data/test/docs/autogenerated/activity_basics_test.rb +72 -0
- data/test/docs/autogenerated/composable_variable_mapping_test.rb +880 -0
- data/test/docs/autogenerated/fast_track_layout_test.rb +76 -0
- data/test/docs/autogenerated/mechanics_test.rb +382 -0
- data/test/docs/autogenerated/sequence_options_test.rb +202 -0
- data/test/docs/autogenerated/subprocess_test.rb +257 -0
- data/test/docs/autogenerated/wiring_api_test.rb +435 -0
- data/test/docs/developer_test.rb +27 -0
- data/test/docs/public_call_monkeypatching_test.rb +96 -0
- data/test/docs/result_test.rb +38 -0
- data/test/docs/step_dsl_test.rb +93 -0
- data/test/operation_test.rb +53 -13
- data/test/result_test.rb +1 -1
- data/test/test_helper.rb +17 -5
- data/test/trace_test.rb +3 -19
- data/trailblazer-operation.gemspec +3 -2
- metadata +50 -25
- data/lib/trailblazer/operation/trace.rb +0 -53
- data/test/callable_test.rb +0 -147
- data/test/docs/doormat_test.rb +0 -190
- data/test/docs/macaroni_test.rb +0 -31
- data/test/skill_test.rb +0 -66
- data/test/wire_test.rb +0 -113
- data/test/wiring/defaults_test.rb +0 -193
- data/test/wiring/subprocess_test.rb +0 -70
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 318d6a14d3ed10922cd2b8a2ec9d67f3d73672488c4833ddfa883ab13c382fe3
|
4
|
+
data.tar.gz: 3432c41d2f36efa9f313f2da68195dfab92b486881db581c03430955202c188b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9d53cc20604c0e11912e4822ce0ab6cc5f05da4a7f7a4cc688da2d350bf859a2e7863f36324bd2c1015ec3ed38118f9ad0e6dcd424229552c0ad6853f760f0af
|
7
|
+
data.tar.gz: e897df0be7f3530c8f8f826ace7db4e0255ce055bda7cbdae995596d91cad2bdd19cbd21f6b2645507ef4a4b7dd71896c94ca78ab4d75960f8ef23bff2a10ba1
|
data/.github/workflows/ci.yml
CHANGED
@@ -5,10 +5,10 @@ jobs:
|
|
5
5
|
strategy:
|
6
6
|
fail-fast: false
|
7
7
|
matrix:
|
8
|
-
ruby: [2.5, 2.6, 2.7, '3.0', '3.1', '3.2', 'jruby']
|
8
|
+
ruby: [2.5, 2.6, 2.7, '3.0', '3.1', '3.2', "3.3", 'jruby']
|
9
9
|
runs-on: ubuntu-latest
|
10
10
|
steps:
|
11
|
-
- uses: actions/checkout@
|
11
|
+
- uses: actions/checkout@v4
|
12
12
|
- uses: ruby/setup-ruby@v1
|
13
13
|
with:
|
14
14
|
ruby-version: ${{ matrix.ruby }}
|
data/CHANGES.md
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
## 0.11.0
|
2
|
+
|
3
|
+
* Introduce `Operation.call_with_public_interface_from_call` which merges `ctx` and `circuit_options`
|
4
|
+
accordingly, so the overrider of `Operation.call_with_public_interface` gets correct args.
|
5
|
+
* Removing `Operation.trace`, you've been warned! Use `Operation.wtf?`. This also removes `Result#wtf`.
|
6
|
+
See [https://github.com/trailblazer/trailblazer-operation/blob/3f821c7d576e7ccccf580fbd8c9305501fdc5d2c/test/trace_test.rb#L22](this sample test case)
|
7
|
+
if you need a more low-level interface to tracing.
|
8
|
+
* No need to pass `:exec_context` in `#call_with_public_interface`. This is done in `Strategy.call`.
|
9
|
+
* Rename `Result#event` to `Result#terminus` for consistency. Deprecate `Result#event`.
|
10
|
+
|
11
|
+
## 0.10.1
|
12
|
+
|
13
|
+
* Deprecate `Operation.trace` and `Result#wtf?` in favor of `Operation.wtf?`.
|
14
|
+
* Use `trailblazer-developer-0.1.0`.
|
15
|
+
|
1
16
|
## 0.10.0
|
2
17
|
|
3
18
|
* Require `trailblazer-activity-dsl-linear-1.2.0`.
|
@@ -25,7 +25,7 @@ class Trailblazer::Operation
|
|
25
25
|
end
|
26
26
|
|
27
27
|
private def context_for_fields(fields, (ctx, flow_options), **)
|
28
|
-
|
28
|
+
_ctx_with_fields = Trailblazer::Context(fields, ctx, flow_options[:context_options]) # TODO: redundant to options_for_public_call.
|
29
29
|
end
|
30
30
|
|
31
31
|
def call_with_circuit_interface((ctx, flow_options), **circuit_options)
|
@@ -16,7 +16,16 @@ module Trailblazer
|
|
16
16
|
def call(options = {}, flow_options = {}, **circuit_options)
|
17
17
|
return call_with_circuit_interface(options, **circuit_options) if options.is_a?(Array) # This is kind of a hack that could be well hidden if Ruby had method overloading. Goal is to simplify the call thing as we're fading out Operation::public_call anyway.
|
18
18
|
|
19
|
-
|
19
|
+
call_with_public_interface_from_call(options, flow_options, **circuit_options)
|
20
|
+
end
|
21
|
+
|
22
|
+
# @private Please do not override this method as it might get removed.
|
23
|
+
def call_with_public_interface_from_call(options, flow_options, **circuit_options)
|
24
|
+
# normalize options.
|
25
|
+
options = options
|
26
|
+
.merge(circuit_options) # when using Op.call(params:, ...), {circuit_options} will always be ctx variables.
|
27
|
+
|
28
|
+
call_with_public_interface(options, flow_options)
|
20
29
|
end
|
21
30
|
|
22
31
|
# Default {@activity} call interface which doesn't accept {circuit_options}
|
@@ -25,24 +34,19 @@ module Trailblazer
|
|
25
34
|
#
|
26
35
|
# @return [Operation::Railway::Result]
|
27
36
|
#
|
28
|
-
# @
|
37
|
+
# @semi-public It's OK to override this method.
|
29
38
|
def call_with_public_interface(options, flow_options, invoke_class: Activity::TaskWrap, **circuit_options)
|
30
39
|
flow_options = flow_options_for_public_call(flow_options)
|
31
|
-
|
32
|
-
# In Ruby < 3, calling Op.(params: {}, "current_user" => user) results in both {circuit_options} and {options} containing variables.
|
33
|
-
# In Ruby 3.0, **circuit_options is always empty.
|
34
|
-
options = circuit_options.any? ? circuit_options.merge(options) : options
|
35
|
-
|
36
40
|
ctx = options_for_public_call(options, flow_options)
|
37
41
|
|
38
|
-
#
|
39
|
-
|
42
|
+
# Call the activity as it if was a step in an endpoint.
|
43
|
+
|
44
|
+
# This will result in invoking {self.call_with_circuit_interface}.
|
40
45
|
signal, (ctx, flow_options) = invoke_class.invoke(
|
41
46
|
self,
|
42
47
|
[ctx, flow_options],
|
43
|
-
|
44
|
-
#
|
45
|
-
container_activity: Activity::TaskWrap.container_activity_for(self, wrap_static: initial_wrap_static)
|
48
|
+
container_activity: Activity::TaskWrap.container_activity_for(self, wrap_static: initial_wrap_static), # we cannot make this static because of {self} unless we override {#inherited}.
|
49
|
+
**circuit_options # this will always be an empty hash if coming from #{call_with_public_interface_from_call}.
|
46
50
|
)
|
47
51
|
|
48
52
|
# Result is successful if the activity ended with an End event derived from Railway::End::Success.
|
@@ -83,15 +87,21 @@ module Trailblazer
|
|
83
87
|
call_with_public_interface(options, flow_options, {invoke_class: Activity::TaskWrap})
|
84
88
|
end
|
85
89
|
|
90
|
+
# This TaskWrap step replaces the default {call_task} step for this very operation.
|
91
|
+
# Instead of invoking the operation using {Operation.call}, it does {Operation.call_with_circuit_interface},
|
92
|
+
# so we don't invoke {Operation.call} twice.
|
93
|
+
#
|
94
|
+
# I don't really like this "hack", but it's the only way until we get method overloading.
|
95
|
+
#
|
86
96
|
# @private
|
87
97
|
def self.call_task(wrap_ctx, original_args) # DISCUSS: copied from {TaskWrap.call_task}.
|
88
|
-
|
98
|
+
operation = wrap_ctx[:task]
|
89
99
|
|
90
100
|
original_arguments, original_circuit_options = original_args
|
91
101
|
|
92
102
|
# Call the actual task we're wrapping here.
|
93
103
|
# puts "~~~~wrap.call: #{task}"
|
94
|
-
return_signal, return_args =
|
104
|
+
return_signal, return_args = operation.call_with_circuit_interface(original_arguments, **original_circuit_options)
|
95
105
|
|
96
106
|
# DISCUSS: do we want original_args here to be passed on, or the "effective" return_args which are different to original_args now?
|
97
107
|
wrap_ctx = wrap_ctx.merge(return_signal: return_signal, return_args: return_args)
|
@@ -10,20 +10,26 @@ module Trailblazer
|
|
10
10
|
def self.fail_fast!; Activity::FastTrack::FailFast end
|
11
11
|
def self.pass_fast!; Activity::FastTrack::PassFast end
|
12
12
|
# @param options Context
|
13
|
-
# @param
|
14
|
-
def self.Result(
|
15
|
-
Result.new(
|
13
|
+
# @param terminus The last emitted signal in a circuit is the end event/terminus.
|
14
|
+
def self.Result(terminus, options, *)
|
15
|
+
Result.new(terminus.kind_of?(End::Success), options, terminus)
|
16
16
|
end
|
17
17
|
|
18
|
-
# The Railway::Result knows about its binary state, the context (data), and
|
18
|
+
# The Railway::Result knows about its binary state, the context (data), and
|
19
|
+
# the reached terminus of the circuit.
|
19
20
|
class Result < Result # Operation::Result
|
20
|
-
def initialize(success, data,
|
21
|
+
def initialize(success, data, terminus)
|
21
22
|
super(success, data)
|
22
23
|
|
23
|
-
@
|
24
|
+
@terminus = terminus
|
24
25
|
end
|
25
26
|
|
26
|
-
|
27
|
+
def event
|
28
|
+
Activity::Deprecate.warn caller_locations[0], %(Using `Result#event` is deprecated, please use `Result#terminus`)
|
29
|
+
terminus
|
30
|
+
end
|
31
|
+
|
32
|
+
attr_reader :terminus
|
27
33
|
end
|
28
34
|
|
29
35
|
module End
|
@@ -50,8 +50,8 @@ module Trailblazer
|
|
50
50
|
require "trailblazer/operation/public_call" # TODO: Remove in 3.0.
|
51
51
|
extend PublicCall # ::call(params: .., current_user: ..)
|
52
52
|
|
53
|
-
require "trailblazer/operation/
|
54
|
-
extend
|
53
|
+
require "trailblazer/operation/wtf"
|
54
|
+
extend Wtf # ::trace
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
data/test/call_test.rb
CHANGED
@@ -41,21 +41,22 @@ class CallTest < Minitest::Spec
|
|
41
41
|
result.event.must_equal Update.to_h[:outputs].find { |output| output.semantic == :failure }.signal
|
42
42
|
end
|
43
43
|
|
44
|
+
def self.add_1(wrap_ctx, original_args)
|
45
|
+
ctx, = original_args[0]
|
46
|
+
ctx[:seq] << 1
|
47
|
+
return wrap_ctx, original_args # yay to mutable state. not.
|
48
|
+
end
|
49
|
+
|
44
50
|
it "invokes with the taskWrap" do
|
45
51
|
operation = Class.new(Trailblazer::Operation) do
|
46
52
|
include Trailblazer::Activity::Testing.def_steps(:a)
|
47
53
|
|
48
|
-
def self.add_1(wrap_ctx, original_args)
|
49
|
-
ctx, = original_args[0]
|
50
|
-
ctx[:seq] << 1
|
51
|
-
return wrap_ctx, original_args # yay to mutable state. not.
|
52
|
-
end
|
53
|
-
|
54
54
|
merge = [
|
55
|
-
[Trailblazer::Activity::TaskWrap::Pipeline.method(:insert_before), "task_wrap.call_task", ["user.add_1", method(:add_1)]]
|
56
55
|
]
|
57
56
|
|
58
|
-
step :a, extensions: [Trailblazer::Activity::TaskWrap::Extension(
|
57
|
+
step :a, extensions: [Trailblazer::Activity::TaskWrap::Extension.WrapStatic(
|
58
|
+
[CallTest.method(:add_1), prepend: "task_wrap.call_task", id: "user.add_1"]
|
59
|
+
)]
|
59
60
|
end
|
60
61
|
|
61
62
|
# normal operation invocation
|
@@ -64,10 +65,31 @@ class CallTest < Minitest::Spec
|
|
64
65
|
result.inspect(:seq).must_equal %{<Result:true [[1, :a]] >}
|
65
66
|
|
66
67
|
# with tracing
|
67
|
-
result = operation.
|
68
|
+
result = operation.wtf?(seq: [])
|
68
69
|
|
69
70
|
result.inspect(:seq).must_equal %{<Result:true [[1, :a]] >}
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
it "calls with the taskWrap defined for operation using circuit interface" do
|
75
|
+
operation = Class.new(Trailblazer::Operation) do
|
76
|
+
include Trailblazer::Activity::Testing.def_steps(:a)
|
77
|
+
|
78
|
+
step :a
|
79
|
+
end
|
80
|
+
|
81
|
+
my_extension = Trailblazer::Activity::TaskWrap::Extension(
|
82
|
+
[CallTest.method(:add_1), id: "my.add_1", append: "task_wrap.call_task"]
|
83
|
+
)
|
84
|
+
|
85
|
+
# circuit interface invocation using call
|
86
|
+
signal, (ctx, _) = operation.call(
|
87
|
+
[{seq: []}, {}],
|
88
|
+
wrap_runtime: Hash.new(my_extension),
|
89
|
+
runner: Trailblazer::Activity::TaskWrap::Runner
|
90
|
+
)
|
70
91
|
|
71
|
-
|
92
|
+
assert_equal signal.to_h[:semantic], :success
|
93
|
+
assert_equal ctx[:seq], [1, :a, 1, 1]
|
72
94
|
end
|
73
95
|
end
|
@@ -28,10 +28,14 @@ class ClassDependenciesTest < Minitest::Spec
|
|
28
28
|
end
|
29
29
|
|
30
30
|
# "model.class" gets injected automatically just before {Index}.
|
31
|
-
Home.({params: {}})
|
31
|
+
result = Home.({params: {}})
|
32
|
+
assert_result result, {:"model.class"=>Module, :params=>{}, :a=>Module}
|
33
|
+
# .inspect.must_equal %{<Result:true #<Trailblazer::Context::Container wrapped_options={\"model.class\"=>Module} mutable_options=#<Trailblazer::Context::Container wrapped_options={:params=>{}} mutable_options={\"a\"=>Module}>> >}
|
32
34
|
|
33
35
|
# "model.class" gets injected by user and overrides class dependencies.
|
34
|
-
Home.({params: {}, "model.class" => Symbol})
|
36
|
+
result = Home.({params: {}, "model.class" => Symbol})
|
37
|
+
assert_result result, {:"model.class"=>Symbol, :params=>{}, :a=>Symbol }
|
38
|
+
# .inspect.must_equal %{<Result:true #<Trailblazer::Context::Container wrapped_options={\"model.class\"=>Module} mutable_options=#<Trailblazer::Context::Container wrapped_options={:params=>{}, \"model.class\"=>Symbol} mutable_options={\"a\"=>Symbol}>> >}
|
35
39
|
|
36
40
|
|
37
41
|
class Dashboard < Trailblazer::Operation
|
@@ -43,8 +47,8 @@ class ClassDependenciesTest < Minitest::Spec
|
|
43
47
|
end
|
44
48
|
|
45
49
|
# TODO: "model.class" gets injected automatically in {Dashboard} and overrides the {Index} input.
|
46
|
-
Dashboard.({params: {}}).inspect
|
47
|
-
|
50
|
+
assert_equal Dashboard.({params: {}}).inspect,
|
51
|
+
%(<Result:true #<Trailblazer::Context::Container wrapped_options=#{{"model.class" => Module}} mutable_options=#<Trailblazer::Context::Container wrapped_options=#{{"model.class" => Float}} mutable_options=#<Trailblazer::Context::Container wrapped_options=#{{"model.class" => Float}} mutable_options=#<Trailblazer::Context::Container wrapped_options=#{{:params => {}}} mutable_options=#{{:Dashboard => Float, "a" => Float}}>>>> >)
|
48
52
|
end
|
49
53
|
|
50
54
|
describe "inheritance" do
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# THIS FILE IS AUTOGENERATED FROM trailblazer-activity-dsl-linear/test/docs/activity_basics_test.rb
|
2
|
+
require "test_helper"
|
3
|
+
|
4
|
+
module X
|
5
|
+
class DocsActivityTest < Minitest::Spec
|
6
|
+
it "basic activity" do
|
7
|
+
Memo = Struct.new(:options) do
|
8
|
+
def save
|
9
|
+
true
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
#:memo-create
|
14
|
+
module Memo::Operation
|
15
|
+
class Create < Trailblazer::Operation
|
16
|
+
step :validate
|
17
|
+
#~body
|
18
|
+
step :save
|
19
|
+
left :handle_errors
|
20
|
+
step :notify
|
21
|
+
#~meths
|
22
|
+
include T.def_steps(:validate, :save, :handle_errors, :notify)
|
23
|
+
|
24
|
+
#:save
|
25
|
+
def save(ctx, params:, **)
|
26
|
+
memo = Memo.new(params[:memo])
|
27
|
+
memo.save
|
28
|
+
|
29
|
+
ctx[:model] = memo # you can write to the {ctx}.
|
30
|
+
end
|
31
|
+
#:save end
|
32
|
+
|
33
|
+
def notify(ctx, **)
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
#~body end
|
38
|
+
def validate(ctx, params:, **) # home-made validation
|
39
|
+
params.key?(:memo) &&
|
40
|
+
params[:memo].key?(:text) &&
|
41
|
+
params[:memo][:text].size > 9
|
42
|
+
# return value matters!
|
43
|
+
end
|
44
|
+
#~meths end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
#:memo-create end
|
48
|
+
|
49
|
+
#:memo-call
|
50
|
+
result = Memo::Operation::Create.(
|
51
|
+
params: {memo: {text: "Do not forget!"}}
|
52
|
+
)
|
53
|
+
|
54
|
+
result.success? # => true
|
55
|
+
puts result.terminus.to_h[:semantic] #=> :success
|
56
|
+
#:memo-call end
|
57
|
+
|
58
|
+
#:memo-call-model
|
59
|
+
result = Memo::Operation::Create.(
|
60
|
+
params: {memo: {text: "Do not forget!"}}
|
61
|
+
)
|
62
|
+
|
63
|
+
#~ctx_to_result
|
64
|
+
puts result[:model] #=> #<Memo id: 1 text: "Do not forget!">
|
65
|
+
#:memo-call-model end
|
66
|
+
#~ctx_to_result end
|
67
|
+
|
68
|
+
assert_equal result.terminus.inspect, %(#<Trailblazer::Activity::Railway::End::Success semantic=:success>)
|
69
|
+
#~ignore end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|