trailblazer-operation 0.2.2 → 0.2.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3374814d5a9e505e40d20d3598a3d67fd868a476659ab7a1c73685aa7a8cc375
4
- data.tar.gz: 1e26729cfc2319be1644de1bdb38bcf35715f25adc355ecdb386d7abc5cb158f
3
+ metadata.gz: 9087723ae9650669c304ea1451156be3a8b1d42cb04a46bd228ab7060b8b321c
4
+ data.tar.gz: 193d554218c156f0817692a6841ea55ddf5b87b537bc52957b586de5a6487826
5
5
  SHA512:
6
- metadata.gz: 3d4b658f8f3c97d2b011949fbc19b2e58ea8e2b5ce192dd280540a6040429b20536ddb400f29c0a6be19a7588ab360f928071d2bcef6c69d88c84a24a9470abe
7
- data.tar.gz: 05fc186cec428608351635c2e33f196489e4a813913574019ad1f95a1d90d0b974a2e0b33154ed0feb9d785eee962e7fc8205f11c364bf423e058ce484894398
6
+ metadata.gz: c60ef931a4c9f45be7285700d29e8ac5f5d912634df7fdbae07014283d1c60731469eececbe2aeecfa1bb8c3531ed9703b00d21e99be1d5f4c705624a1ff7821
7
+ data.tar.gz: d3684f685583bc322efd275fc8b14653cc408c4d56c18ab099753480166b0ad6882ad4cf9fa103bb781ca8d73b4f164f331abd7bc8396c7085bf748e828c3be3
data/Gemfile CHANGED
@@ -20,4 +20,4 @@ gem "benchmark-ips"
20
20
 
21
21
  # gem "declarative", path: "../declarative"
22
22
 
23
- gem "trailblazer-activity"#, path: "../circuit"
23
+ gem "trailblazer-activity", path: "../trailblazer-circuit"
@@ -6,10 +6,11 @@ require "trailblazer/context"
6
6
  require "trailblazer/container_chain"
7
7
 
8
8
  require "trailblazer/activity"
9
- require "trailblazer/activity/magnetic"
9
+ require "trailblazer/activity/dsl/magnetic"
10
10
 
11
11
 
12
12
  require "trailblazer/operation/variable_mapping"
13
+ require "trailblazer/operation/callable"
13
14
 
14
15
  require "trailblazer/operation/heritage"
15
16
  require "trailblazer/operation/public_call" # TODO: Remove in 3.0.
@@ -78,7 +79,7 @@ module Trailblazer
78
79
 
79
80
  class << self
80
81
  extend Forwardable # TODO: test those helpers
81
- def_delegators :@activity, :Path, :Output, :End
82
+ def_delegators :@activity, :Path, :Output, :End, :Track
82
83
  def_delegators :@activity, :outputs, :debug
83
84
 
84
85
  def step(task, options={}, &block); add_task!(:step, task, options, &block) end
@@ -0,0 +1,42 @@
1
+ module Trailblazer
2
+ class Operation
3
+ # Use {Callable} if you have an operation or any other callable object that does
4
+ # _not_ expose an {Activity interface}. For example, {Operation.call} isn't compatible
5
+ # with activities, hence you need to decorate it using {Callable}. The returned object
6
+ # exposes an {Activity interface}.
7
+ #
8
+ # @param :call [Symbol] Method name to call
9
+ # @param options [Hash] Hash to merge into {circuit_options}, e.g. {:start_task}.
10
+ #
11
+ # @example Create and use a Callable instance.
12
+ # callable = Trailblazer::Operation::Callable( Memo::Create, call: :__call__ )
13
+ # callable.( [ctx, {}] ) #=> Activity interface, ::call will invoke Memo::Create.__call__.
14
+ def self.Callable(*args)
15
+ Callable.new(*args)
16
+ end
17
+
18
+ # Subprocess allows to have tasks with a different call interface and start event.
19
+ # @param activity any object with an {Activity interface}
20
+ class Callable
21
+ include Activity::Interface
22
+
23
+ def initialize(activity, call: :call, **options)
24
+ @activity = activity
25
+ @options = options
26
+ @call = call
27
+ end
28
+
29
+ def call(args, **circuit_options)
30
+ @activity.public_send(@call, args, circuit_options.merge(@options))
31
+ end
32
+
33
+ extend Forwardable
34
+ # @private
35
+ def_delegators :@activity, :to_h, :debug
36
+
37
+ def to_s
38
+ %{#<Trailblazer::Activity::Callable activity=#{@activity}>}
39
+ end
40
+ end
41
+ end
42
+ end
@@ -1,5 +1,5 @@
1
1
  module Trailblazer
2
2
  class Operation
3
- VERSION = "0.2.2"
3
+ VERSION = "0.2.3"
4
4
  end
5
5
  end
@@ -0,0 +1,147 @@
1
+ require "test_helper"
2
+
3
+ class CallableHelper < Minitest::Spec
4
+ Operation = Trailblazer::Operation
5
+ Activity = Trailblazer::Activity
6
+
7
+ module Blog
8
+ Read = ->((options, *args), *) { options["Read"] = 1; [ Activity::Right, [options, *args] ] }
9
+ Next = ->((options, *args), *) { options["NextPage"] = []; [ options["return"], [options, *args] ] }
10
+ Comment = ->((options, *args), *) { options["Comment"] = 2; [ Activity::Right, [options, *args] ] }
11
+ end
12
+
13
+ module User
14
+ Relax = ->((options, *args), *) { options["Relax"]=true; [ Activity::Right, [options, *args] ] }
15
+ end
16
+
17
+ ### Callable( )
18
+ ###
19
+ describe "circuit with 1 level of nesting" do # TODO: test this kind of configuration in dsl_tests somewhere.
20
+ let(:blog) do
21
+ Module.new do
22
+ extend Activity::Path()
23
+
24
+ task task: Blog::Read
25
+ task task: Blog::Next, Output(Activity::Right, :done) => "End.success", Output(Activity::Left, :success) => Track(:success)
26
+ task task: Blog::Comment
27
+ end
28
+ end
29
+
30
+ let(:user) do
31
+ _blog = blog
32
+
33
+ Module.new do
34
+ extend Activity::Path()
35
+
36
+ task task: _blog, _blog.outputs[:success] => Track(:success)
37
+ task task: User::Relax
38
+ end
39
+ end
40
+
41
+ it "ends before comment, on next_page" do
42
+ user.( [options = { "return" => Activity::Right }] ).must_equal(
43
+ [user.outputs[:success].signal, [{"return"=>Trailblazer::Activity::Right, "Read"=>1, "NextPage"=>[], "Relax"=>true}]]
44
+ )
45
+
46
+ options.must_equal({"return"=>Trailblazer::Activity::Right, "Read"=>1, "NextPage"=>[], "Relax"=>true})
47
+ end
48
+ end
49
+
50
+ ### Callable( End1, End2 )
51
+ ###
52
+ describe "circuit with 2 end events in the nested process" do
53
+ let(:blog) do
54
+ Module.new do
55
+ extend Activity::Path()
56
+
57
+ task task: Blog::Read
58
+ task task: Blog::Next, Output(Activity::Right, :success___) => :__success, Output(Activity::Left, :retry___) => _retry=End(:retry)
59
+ end
60
+ end
61
+
62
+ let(:user) do
63
+ _blog = blog
64
+
65
+ Module.new do
66
+ extend Activity::Path()
67
+
68
+ task task: _blog, _blog.outputs[:success] => Track(:success), _blog.outputs[:retry] => "End.success"
69
+ task task: User::Relax
70
+ end
71
+ end
72
+
73
+ it "runs from Callable->default to Relax" do
74
+ user.( [ options = { "return" => Activity::Right } ] ).must_equal [
75
+ user.outputs[:success].signal,
76
+ [ {"return"=>Activity::Right, "Read"=>1, "NextPage"=>[], "Relax"=>true} ]
77
+ ]
78
+
79
+ options.must_equal({"return"=>Activity::Right, "Read"=>1, "NextPage"=>[], "Relax"=>true})
80
+ end
81
+
82
+ it "runs from other Callable end" do
83
+ user.( [ options = { "return" => Activity::Left } ] ).must_equal [
84
+ user.outputs[:success].signal,
85
+ [ {"return"=>Activity::Left, "Read"=>1, "NextPage"=>[]} ]
86
+ ]
87
+
88
+ options.must_equal({"return"=>Activity::Left, "Read"=>1, "NextPage"=>[]})
89
+ end
90
+
91
+ #---
92
+ #- Callable( activity, start_at )
93
+ let(:with_nested_and_start_at) do
94
+ _blog = blog
95
+
96
+ Module.new do
97
+ extend Activity::Path()
98
+
99
+ task task: Operation::Callable( _blog, task: Blog::Next ), _blog.outputs[:success] => Track(:success)
100
+ task task: User::Relax
101
+ end
102
+ end
103
+
104
+ it "runs Callable from alternative start" do
105
+ with_nested_and_start_at.( [options = { "return" => Activity::Right }] ).
106
+ must_equal [
107
+ with_nested_and_start_at.outputs[:success].signal,
108
+ [ {"return"=>Activity::Right, "NextPage"=>[], "Relax"=>true} ]
109
+ ]
110
+
111
+ options.must_equal({"return"=>Activity::Right, "NextPage"=>[], "Relax"=>true})
112
+ end
113
+
114
+ #---
115
+ #- Callable( activity, call: :__call__ ) { ... }
116
+ describe "Callable with :call option" do
117
+ let(:process) do
118
+ class Workout
119
+ def self.__call__((options, *args), *)
120
+ options[:workout] = 9
121
+
122
+ return Activity::Right, [options, *args]
123
+ end
124
+ end
125
+
126
+ subprocess = Operation::Callable( Workout, call: :__call__ )
127
+
128
+ Module.new do
129
+ extend Activity::Path()
130
+
131
+ task task: subprocess
132
+ task task: User::Relax
133
+ end
134
+ end
135
+
136
+ it "runs Callable process with __call__" do
137
+ process.( [options = { "return" => Activity::Right }] ).
138
+ must_equal [
139
+ process.outputs[:success].signal,
140
+ [{"return"=>Activity::Right, :workout=>9, "Relax"=>true}]
141
+ ]
142
+
143
+ options.must_equal({"return"=>Activity::Right, :workout=>9, "Relax"=>true})
144
+ end
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,23 @@
1
+ require "test_helper"
2
+
3
+ class DocsActivityTest < Minitest::Spec
4
+ Memo = Struct.new(:body)
5
+
6
+ class Memo::Create < Trailblazer::Operation
7
+ step :create_model
8
+ def create_model(ctx, params:, **)
9
+ ctx[:model] = Memo.new(params[:body])
10
+ end
11
+ end
12
+
13
+ #:describe
14
+ describe Memo::Create do
15
+ it "creates a sane Memo instance" do
16
+ result = Memo::Create.( params: { body: "Enjoy an IPA" } )
17
+
18
+ result.success?.must_equal true
19
+ result[:model].body.must_equal "Enjoy an IPA"
20
+ end
21
+ end
22
+ #:describe end
23
+ end
@@ -314,7 +314,7 @@ class WiringsDocSeqOptionsTest < Minitest::Spec
314
314
  Memo = Id::Memo
315
315
  #:id-inspect
316
316
  Trailblazer::Operation.introspect( Memo::Create )
317
- #=> [>create_model,>validate_params,>save]
317
+ #=> [>create_memo,>validate_params,>save]
318
318
  #:id-inspect end
319
319
 
320
320
  Trailblazer::Operation.introspect( Memo::Create ).must_equal %{[>create_memo,>validate_params,>save]}
@@ -368,10 +368,10 @@ class WiringsDocRecoverTest < Minitest::Spec
368
368
  #:fail-success
369
369
  class Memo::Upload < Trailblazer::Operation
370
370
  step :upload_to_s3
371
- fail :upload_to_azure, Output(:success) => :success
372
- fail :upload_to_b2, Output(:success) => :success
371
+ fail :upload_to_azure, Output(:success) => Track(:success)
372
+ fail :upload_to_b2, Output(:success) => Track(:success)
373
373
  fail :log_problem
374
- #~fail-success-methods
374
+ #~methods
375
375
  #:fail-success-s3
376
376
  def upload_to_s3(options, s3:, **)
377
377
  options[:s3] = s3 # the actual upload is dispatched here and result collected.
@@ -389,7 +389,7 @@ class WiringsDocRecoverTest < Minitest::Spec
389
389
  def log_problem(options, **)
390
390
  options[:problem] = "All uploads failed."
391
391
  end
392
- #~fail-success-methods end
392
+ #~methods end
393
393
  end
394
394
  #:fail-success end
395
395
 
@@ -477,11 +477,11 @@ class WiringsDocDeciderTest < Minitest::Spec
477
477
 
478
478
  #:decider
479
479
  class Memo::Upsert < Trailblazer::Operation
480
- step :find_model, Output(:failure) => :create_route
480
+ step :find_model, Output(:failure) => Track(:create_route)
481
481
  step :update
482
482
  step :create, magnetic_to: [:create_route]
483
483
  step :save
484
- #~decm
484
+ #~methods
485
485
  def find_model(options, id:nil, **)
486
486
  options[:model] = Memo.find(id)
487
487
  end
@@ -498,7 +498,7 @@ class WiringsDocDeciderTest < Minitest::Spec
498
498
  def save(options, **)
499
499
  options[:save] = true
500
500
  end
501
- #~decm end
501
+ #~methods end
502
502
  end
503
503
  #:decider end
504
504
 
@@ -126,8 +126,8 @@ class NestedFastTrackTest < Minitest::Spec
126
126
  describe "Nested, fast_track: true and all its outputs given" do
127
127
  let(:update) do
128
128
  Class.new(Trailblazer::Operation) do
129
- step task: Trailblazer::Activity::Subprocess( Edit, call: :__call__ ), id: "Subprocess/",
130
- plus_poles: Trailblazer::Activity::Magnetic::DSL::PlusPoles::from_outputs( Edit.outputs ),
129
+ step task: Trailblazer::Operation::Callable( Edit, call: :__call__ ), id: "Callable/",
130
+ outputs: Edit.outputs ,
131
131
  fast_track: true
132
132
  step :b
133
133
  fail :f
@@ -151,8 +151,8 @@ class NestedFastTrackTest < Minitest::Spec
151
151
  Class.new(Trailblazer::Operation) do
152
152
  include Steps
153
153
 
154
- step task: Trailblazer::Activity::Subprocess( Edit, call: :__call__ ), id: "Subprocess/",
155
- plus_poles: Trailblazer::Activity::Magnetic::DSL::PlusPoles::from_outputs( Edit.outputs ) # all outputs given means it "works"
154
+ step task: Trailblazer::Operation::Callable( Edit, call: :__call__ ), id: "Callable/",
155
+ outputs: Edit.outputs # all outputs given means it "works"
156
156
  step :b
157
157
  fail :f
158
158
  end
@@ -173,9 +173,9 @@ class NestedFastTrackTest < Minitest::Spec
173
173
  Class.new(Trailblazer::Operation) do
174
174
  include Steps
175
175
 
176
- step({task: Trailblazer::Activity::Subprocess( Edit, call: :__call__ ), id: "Subprocess/",
177
- plus_poles: Trailblazer::Activity::Magnetic::DSL::PlusPoles::from_outputs( Edit.outputs )},
178
- {Output(:pass_fast) => :success, Output(:fail_fast) => :failure} )# manually rewire the fast-track outputs to "conventional" railway ends.
176
+ step({task: Trailblazer::Operation::Callable( Edit, call: :__call__ ), id: "Callable/",
177
+ outputs: Edit.outputs },
178
+ {Output(:pass_fast) => Track(:success), Output(:fail_fast) => Track(:failure)} )# manually rewire the fast-track outputs to "conventional" railway ends.
179
179
 
180
180
  step :b
181
181
  fail :f
@@ -31,9 +31,9 @@ class InspectTest < Minitest::Spec
31
31
  5 ============================>finalize!}
32
32
  end
33
33
 
34
- describe "step with only one plus pole (happens with Nested)" do
34
+ describe "step with only one output (happens with Nested)" do
35
35
  class Present < Trailblazer::Operation
36
- pass :ok!, plus_poles: Trailblazer::Activity::Magnetic::DSL::PlusPoles::from_outputs( :success => Trailblazer::Activity.Output("signal", :success) )
36
+ pass :ok!, outputs: {:success => Trailblazer::Activity::Output("signal", :success)}
37
37
  end
38
38
 
39
39
  it do
@@ -5,8 +5,6 @@ require "test_helper"
5
5
  # macro [ task, {name}, { alteration: }, {task_outputs} ] # for eg. nested
6
6
 
7
7
  class MacroTest < Minitest::Spec
8
- PlusPoles = Trailblazer::Activity::Magnetic::DSL::PlusPoles
9
-
10
8
  MacroB = ->(( options, *args ), **) do
11
9
  options[:B] = true # we were here!
12
10
 
@@ -26,7 +24,7 @@ class MacroTest < Minitest::Spec
26
24
 
27
25
  class Create < Trailblazer::Operation
28
26
  step :a
29
- step( task: MacroB, id: :MacroB, plus_poles: Test.plus_poles_for("Allgood" => :success, "Fail!" => :failure, "Winning" => :pass_fast) )
27
+ step task: MacroB, id: :MacroB, outputs: { :success => Activity::Output("Allgood", :success), :failure => Activity::Output("Fail!", :failure), :pass_fast => Activity::Output("Winning", :pass_fast) }
30
28
  step :c
31
29
 
32
30
  def a(options, **); options[:a] = true end
@@ -42,10 +40,11 @@ class MacroTest < Minitest::Spec
42
40
 
43
41
  #- user overrides :plus_poles
44
42
  class Update < Trailblazer::Operation
45
- macro = { task: MacroB, id: :MacroB, plus_poles: Test.plus_poles_for("Allgood" => :success, "Fail!" => :failure, "Winning" => :pass_fast) }
43
+ macro = { task: MacroB, id: :MacroB, outputs: { :success => Activity::Output("Allgood", :success), :failure => Activity::Output("Fail!", :failure), :pass_fast => Activity::Output("Winning", :pass_fast) } }
46
44
 
47
45
  step :a
48
- step macro, plus_poles: Test.plus_poles_for("Allgood" => :failure, "Fail!" => :success, "Winning" => :fail_fast)
46
+ step macro, outputs: { :success => Activity::Output("Fail!", :success), :fail_fast => Activity::Output("Winning", :fail_fast), :failure => Activity::Output("Allgood", :failure) }
47
+ # plus_poles: Test.plus_poles_for("Allgood" => :failure, "Fail!" => :success, "Winning" => :fail_fast)
49
48
  step :c
50
49
 
51
50
  def a(options, **); options[:a] = true end
@@ -35,5 +35,5 @@ module Test
35
35
  end
36
36
 
37
37
  Minitest::Spec.class_eval do
38
-
38
+ Activity = Trailblazer::Activity
39
39
  end
@@ -12,7 +12,7 @@ class TraceTest < Minitest::Spec
12
12
 
13
13
  class Create < Trailblazer::Operation
14
14
  step ->(options, a_return:, **) { options[:a] = a_return }, id: "Create.task.a"
15
- step( {task: B, id: "MyNested"}, B.outputs[:success] => :success )
15
+ step( {task: B, id: "MyNested"}, B.outputs[:success] => Track(:success) )
16
16
  step ->(options, **) { options[:c] = true }, id: "Create.task.c"
17
17
  step ->(options, params:, **) { params.any? }, id: "Create.task.params"
18
18
 
@@ -79,8 +79,8 @@ require "test_helper"
79
79
  class WireDefaultsEarlyExitSuccessTest < Minitest::Spec
80
80
  class Create < Trailblazer::Operation
81
81
  step :a
82
- fail :b, Output(:success) => :success #{}"End.success"
83
- fail :c, Output(:success) => :success
82
+ fail :b, Output(:success) => Track(:success) #{}"End.success"
83
+ fail :c, Output(:success) => Track(:success)
84
84
 
85
85
  Test.step(self, :a, :b, :c)
86
86
  end
@@ -99,7 +99,7 @@ class WireDefaultsEarlyExitSuccessTest < Minitest::Spec
99
99
 
100
100
 
101
101
  # #---
102
- # # with => :success, steps can still be added before End.success and they will be executed.
102
+ # # with => Track(:success), steps can still be added before End.success and they will be executed.
103
103
  class Update < Create
104
104
  pass :d
105
105
 
@@ -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.4.2", "< 0.5.0"
20
+ spec.add_dependency "trailblazer-activity", ">= 0.5.0", "< 0.7.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.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Sutterer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-01-24 00:00:00.000000000 Z
11
+ date: 2018-03-01 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.4.2
19
+ version: 0.5.0
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: 0.5.0
22
+ version: 0.7.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.4.2
29
+ version: 0.5.0
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: 0.5.0
32
+ version: 0.7.0
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: trailblazer-context
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -106,6 +106,7 @@ files:
106
106
  - README.md
107
107
  - Rakefile
108
108
  - lib/trailblazer/operation.rb
109
+ - lib/trailblazer/operation/callable.rb
109
110
  - lib/trailblazer/operation/deprecated_macro.rb
110
111
  - lib/trailblazer/operation/heritage.rb
111
112
  - lib/trailblazer/operation/inject.rb
@@ -123,9 +124,11 @@ files:
123
124
  - lib/trailblazer/operation/version.rb
124
125
  - test/benchmark/skill_resolver_benchmark.rb
125
126
  - test/call_test.rb
127
+ - test/callable_test.rb
126
128
  - test/class_dependencies_test.rb
127
129
  - test/docs/doormat_test.rb
128
130
  - test/docs/macaroni_test.rb
131
+ - test/docs/operation_test.rb
129
132
  - test/docs/wiring_test.rb
130
133
  - test/dry_container_test.rb
131
134
  - test/fast_track_test.rb
@@ -178,9 +181,11 @@ summary: Trailblazer's operation object with railway flow and integrated error h
178
181
  test_files:
179
182
  - test/benchmark/skill_resolver_benchmark.rb
180
183
  - test/call_test.rb
184
+ - test/callable_test.rb
181
185
  - test/class_dependencies_test.rb
182
186
  - test/docs/doormat_test.rb
183
187
  - test/docs/macaroni_test.rb
188
+ - test/docs/operation_test.rb
184
189
  - test/docs/wiring_test.rb
185
190
  - test/dry_container_test.rb
186
191
  - test/fast_track_test.rb