lib/trailblazer/macro/nested.rb in trailblazer-macro-2.1.5 vs lib/trailblazer/macro/nested.rb in trailblazer-macro-2.1.6
- old
+ new
@@ -1,17 +1,17 @@
# per default, everything we pass into a circuit is immutable. it's the ops/act's job to allow writing (via a Context)
module Trailblazer
module Macro
# {Nested} macro.
- def self.Nested(callable, id: "Nested(#{callable})")
+ def self.Nested(callable, id: "Nested(#{callable})", auto_wire: [])
if callable.is_a?(Class) && callable < Nested.operation_class
warn %{[Trailblazer] Using the `Nested()` macro with operations and activities is deprecated. Replace `Nested(Create)` with `Subprocess(Create)`.}
return Nested.operation_class.Subprocess(callable)
end
# dynamic
- task = Nested::Dynamic.new(callable)
+ task = Nested::Dynamic.new(callable, auto_wire: auto_wire)
merge = [
[Activity::TaskWrap::Pipeline.method(:insert_before), "task_wrap.call_task", ["Nested.compute_nested_activity", task.method(:compute_nested_activity)]],
[Activity::TaskWrap::Pipeline.method(:insert_after), "task_wrap.call_task", ["Nested.compute_return_signal", task.method(:compute_return_signal)]],
]
@@ -31,21 +31,28 @@
def self.operation_class
Operation
end
# For dynamic `Nested`s that do not expose an {Activity} interface.
- # Since we do not know its outputs, we have to map them to :success and :failure, only.
#
- # This is what {Nested} in 2.0 used to do, where the outcome could only be true/false (or success/failure).
+ # Dynamic doesn't automatically connect outputs of runtime {Activity}
+ # at compile time (as we don't know which activity will be nested, obviously).
+ # So by default, it only connects good old success/failure ends. But it is also
+ # possible to connect all the ends of all possible dynamic activities
+ # by passing their list to {:auto_wire} option.
+ #
+ # step Nested(:compute_nested, auto_wire: [Create, Update])
class Dynamic
- def initialize(nested_activity_decider)
- @nested_activity_decider = Trailblazer::Option(nested_activity_decider)
+ STATIC_OUTPUTS = {
+ :success => Activity::Output(Activity::Railway::End::Success.new(semantic: :success), :success),
+ :failure => Activity::Output(Activity::Railway::End::Failure.new(semantic: :failure), :failure),
+ }
- @outputs = {
- :success => Activity::Output(Activity::Railway::End::Success.new(semantic: :success), :success),
- :failure => Activity::Output(Activity::Railway::End::Failure.new(semantic: :failure), :failure)
- }
+ def initialize(nested_activity_decider, auto_wire: [])
+ @nested_activity_decider = Trailblazer::Option(nested_activity_decider)
+ @known_activities = Array(auto_wire)
+ @outputs = compute_task_outputs
end
attr_reader :outputs
# TaskWrap step.
@@ -61,15 +68,30 @@
return wrap_ctx, original_args
end
def compute_return_signal(wrap_ctx, original_args)
- # Translate the genuine nested signal to the generic Dynamic end (success/failure, only).
- # Note that here we lose information about what specific event was emitted.
- wrap_ctx[:return_signal] = wrap_ctx[:return_signal].kind_of?(Activity::Railway::End::Success) ?
- @outputs[:success].signal : @outputs[:failure].signal
+ # NOOP when @known_activities are present as all possible signals have been registered already.
+ if @known_activities.empty?
+ # Translate the genuine nested signal to the generic Dynamic end (success/failure, only).
+ # Note that here we lose information about what specific event was emitted.
+ wrap_ctx[:return_signal] = wrap_ctx[:return_signal].kind_of?(Activity::Railway::End::Success) ?
+ @outputs[:success].signal : @outputs[:failure].signal
+ end
return wrap_ctx, original_args
+ end
+
+ private def compute_task_outputs
+ # If :auto_wire is empty, we map outputs to :success and :failure only, for backward compatibility.
+ # This is what {Nested} in 2.0 used to do, where the outcome could only be true/false (or success/failure).
+ return STATIC_OUTPUTS if @known_activities.empty?
+
+ # Merge activity#outputs from all given auto_wirable activities to wire up for this dynamic task.
+ @known_activities.map do |activity|
+ # TODO: Replace this when it's helper gets added.
+ Hash[activity.to_h[:outputs].collect{ |output| [output.semantic, output] }]
+ end.inject(:merge)
end
end
end
end
end