Skip to content

Commit

Permalink
move "test" code to Discovery.
Browse files Browse the repository at this point in the history
  • Loading branch information
apotonick committed Feb 14, 2024
1 parent eef959b commit 4739a7b
Show file tree
Hide file tree
Showing 4 changed files with 255 additions and 190 deletions.
2 changes: 2 additions & 0 deletions lib/trailblazer/workflow.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ module Workflow
require "trailblazer/workflow/state/table"

require "trailblazer/workflow/test/plan"

require "trailblazer/workflow/discovery"
7 changes: 3 additions & 4 deletions lib/trailblazer/workflow/collaboration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@ def initialize(lanes:, message_flow:, options:{})
@message_flow = message_flow
# @initial_lane_positions = Synchronous.initial_lane_positions(lanes.values)
# @options = options # FIXME: test me!!!
end

# attr_reader :initial_lane_positions
# attr_reader :message_flow
# attr_reader :lanes # @private
# TODO: define what we need here, for runtime.
# 1. a Collaboration doesn't mandatorily need its initial_lane_positions, that's only relevant for state discovery or State layer.
end

def to_h
{
Expand Down
119 changes: 119 additions & 0 deletions lib/trailblazer/workflow/discovery.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
module Trailblazer
module Workflow
# DISCUSS: move to state discovery.
module Discovery
module_function

# Find all possible configurations for a {collaboration} by replacing
# its tasks with mocks, and run through all possible paths.
def call(collaboration, start_position:, run_multiple_times: {}, initial_lane_positions: Collaboration::Synchronous.initial_lane_positions(collaboration), message_flow:)
# State discovery:
# The idea is that we collect suspend events and follow up on all their resumes (catch) events.
# We can't see into {Collaboration.call}, meaning we can really only collect public entry points,
# just like a user (like a controller) of our process.
# 1. one problem is, when a decision is involved in the run ahead of us we need to invoke the same
# catch multiple times, with different input data.
# DISCUSS: could we figure out the two different suspend termini that way, to make it easier for users to define
# which outcome is "success"?
#
## DISCUSS: We could probably figure out "binary" paths automatically? That would
# imply we start from a public resume and discover the path?
# we could save work on {run_multiple_times} with this.

resumes_to_invoke = [
[
start_position,
initial_lane_positions,
{}, # ctx_merge
{outcome: :success} # config_payload
]
]

states = []
additional_state_data = {}

already_visited_catch_events = {}
already_visited_catch_events_again = {} # FIXME: well, yeah.

while resumes_to_invoke.any?
(start_position, lane_positions, ctx_merge, config_payload) = resumes_to_invoke.shift
puts "~~~~~~~~~"

ctx = {seq: []}.merge(ctx_merge)
start_task = start_position.to_h[:task]
if (do_again_config = run_multiple_times[start_task]) && !already_visited_catch_events_again[start_task] # TODO: do this by keying by resume event and ctx variable(s).

resumes_to_invoke << [
start_position,
lane_positions, # same positions as the original situation.
do_again_config[:ctx_merge],
do_again_config[:config_payload]
]

already_visited_catch_events_again[start_task] = true
end

# register new state.
# Note that we do that before anything is invoked.
states << state = [lane_positions, start_position] # FIXME: we need to add {configuration} here!

state_data = [ctx.inspect]

configuration, (ctx, flow) = Trailblazer::Workflow::Collaboration::Synchronous.advance(
collaboration,
[ctx, {throw: []}],
{}, # circuit_options

start_position: start_position,
lane_positions: lane_positions, # current position/"state"

message_flow: message_flow,
)

# 3. optional feature: outcome marking
additional_state_data[[state.object_id, :outcome]] = config_payload[:outcome]


# 1. optional feature: tracing
state_data << ctx.inspect # context after. DISCUSS: use tracing?
additional_state_data[[state.object_id, :ctx]] = state_data

# 2. optional feature: remember stop configuration so we can use that in a test.
# raise configuration.inspect
suspend_configuration = configuration
additional_state_data[[state.object_id, :suspend_configuration]] = suspend_configuration

# figure out possible next resumes/catchs:
last_lane = configuration.last_lane
suspend_terminus = configuration.lane_positions[last_lane]

next if suspend_terminus.instance_of?(Trailblazer::Activity::End) # a real end event!
# elsif suspend_terminus.is_a?(Trailblazer::Activity::Railway::End) # a real end event!

# raise suspend_terminus.inspect

# Go through all possible resume/catch events and "remember" them
suspend_terminus.to_h["resumes"].each do |resume_event_id|
resume_event = Trailblazer::Activity::Introspect.Nodes(last_lane, id: resume_event_id).task

unless already_visited_catch_events[resume_event]
resumes_to_invoke << [
Trailblazer::Workflow::Collaboration::Position.new(last_lane, resume_event),
configuration.lane_positions,
{},
{outcome: :success}
]
end

already_visited_catch_events[resume_event] = true
end
end

# {states} is compile-time relevant
# {additional_state_data} is runtime

return states, additional_state_data
end
end
end
end
Loading

0 comments on commit 4739a7b

Please sign in to comment.