Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wire additional outputs (eg, not_found) to protocol/adapter activities #17

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 28 additions & 7 deletions lib/trailblazer/endpoint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,29 @@ def self.build(protocol:, adapter:, domain_activity:, scope_domain_ctx: true, do
# puts

app_protocol = Class.new(protocol) do
step(Subprocess(domain_activity), {inherit: true, id: :domain_activity, replace: :domain_activity,
domain_activity_args = { inherit: true, id: :domain_activity, replace: :domain_activity }
domain_activity_args.merge!(extensions_options)

# FIXME: where does this go?
}.
merge(extensions_options).
merge(instance_exec(&protocol_block)) # the block is evaluated in the {Protocol} context.
# protocol_block is evaluated in the {Protocol} context.
domain_activity_args.merge!(instance_exec(&protocol_block))

# Forward protocol specific stop_events from domain_activity
domain_activity_args.merge!(
Endpoint.wire_additonal_stop_events_from(domain_activity, output_mappings: Endpoint::Protocol::ADDITIONAL_WIRINGS)
)

step(Subprocess(domain_activity), domain_activity_args)
end

# puts Trailblazer::Developer.render(app_protocol)

Class.new(adapter) do
step(Subprocess(app_protocol), {inherit: true, id: :protocol, replace: :protocol})
app_protocol_args = { inherit: true, id: :protocol, replace: :protocol }
app_protocol_args.merge!(
Endpoint.wire_additonal_stop_events_from(app_protocol, output_mappings: Endpoint::Adapter::Web::ADDITIONAL_WIRINGS)
)

step(Subprocess(app_protocol), app_protocol_args)
end # app_adapter

end
Expand Down Expand Up @@ -116,7 +126,7 @@ def self.arguments_for(domain_ctx:, flow_options:, circuit_options: {}, **endpoi
end

# FIXME: name will change! this is for controllers, only!
def self.advance_from_controller(endpoint, success_block:, failure_block:, protocol_failure_block: protocol_failure_block, **argument_options)
def self.advance_from_controller(endpoint, success_block:, failure_block:, protocol_failure_block:, **argument_options)
args = Trailblazer::Endpoint.arguments_for(argument_options)

signal, (ctx, _ ) = Trailblazer::Endpoint.with_or_etc(
Expand All @@ -130,6 +140,17 @@ def self.advance_from_controller(endpoint, success_block:, failure_block:, proto

ctx
end

# Returns any additional stop_events mappings based on activity's wiring.
# This is used to add additional protocol or adapter's wiring at runtime based on the {stop_event} presence.
def self.wire_additonal_stop_events_from(activity, output_mappings:)
graph = Trailblazer::Activity::Introspect::Graph(activity)
semantics = graph.stop_events.collect{ |se| se.to_h[:semantic] }

output_mappings.select do |output, _stop_event|
semantics.include?(output.value)
end
end
end
end
# created: Dry::Matcher::Case.new(
Expand Down
5 changes: 4 additions & 1 deletion lib/trailblazer/endpoint/adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ class Web < Trailblazer::Activity::Path
_403_path = ->(*) { step :_403_status }
# _422_path = ->(*) { step :_422_status } # TODO: this is currently represented by the {failure} track.

ADDITIONAL_WIRINGS = {
Output(:not_found) => Path(track_color: :not_found, connect_to: Id(:protocol_failure), &_404_path),
}

# FIXME: is this really the only way to add an {End} to all this?
@state.update_sequence do |sequence:, **|
sequence = Activity::Path::DSL.append_end(sequence, task: Activity::End.new(semantic: :fail_fast), magnetic_to: :fail_fast, id: "End.fail_fast") # TODO: rename to {protocol_failure}
Expand All @@ -28,7 +32,6 @@ class Web < Trailblazer::Activity::Path
step Subprocess(Protocol), # this will get replaced
id: :protocol,
Output(:not_authorized) => Path(track_color: :not_authorized, connect_to: Id(:protocol_failure), &_403_path),
Output(:not_found) => Path(track_color: :not_found, connect_to: Id(:protocol_failure), &_404_path),
Output(:not_authenticated) => Path(track_color: :not_authenticated, connect_to: Id(:protocol_failure), &_401_path),
Output(:invalid_data) => Track(:failure), # application error, since it's usually a failed validation.
Output(:failure) => Track(:failure) # application error, since it's usually a failed validation.
Expand Down
23 changes: 7 additions & 16 deletions lib/trailblazer/endpoint/protocol.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require "trailblazer/activity/dsl/linear"
require "trailblazer/activity/introspect"

module Trailblazer
class Endpoint
Expand All @@ -15,6 +16,10 @@ class Endpoint
# not_authenticated: 401
# not_authorized: 403
class Protocol < Trailblazer::Activity::Railway
ADDITIONAL_WIRINGS = {
Output(:not_found) => End(:not_found)
}

class Noop < Trailblazer::Activity::Railway
end

Expand All @@ -32,21 +37,8 @@ def self._Path(semantic:, &block) # DISCUSS: the problem with Path currently is

# Here, we test a domain OP with ADDITIONAL explicit ends that get wired to the Adapter (vaidation_error => failure).
# We still need to test the other way round: wiring a "normal" failure to, say, not_found, by inspecting the ctx.
step Subprocess(Noop), id: :domain_activity



# add the {End.not_found} terminus to this Protocol. I'm not sure that's the final style, but since a {Protocol} needs to provide all
# termini for the Adapter this is the only way to get it working right now.
# FIXME: is this really the only way to add an {End} to all this?
@state.update_sequence do |sequence:, **|
sequence = Activity::Path::DSL.append_end(sequence, task: Activity::End.new(semantic: :not_found), magnetic_to: :not_found, id: "End.not_found")
sequence = Activity::Path::DSL.append_end(sequence, task: Activity::End.new(semantic: :invalid_data), magnetic_to: :invalid_data, id: "End.invalid_data")

recompile_activity!(sequence)

sequence
end
step Subprocess(Noop), id: :domain_activity,
Output(:failure) => End(:invalid_data)

# Best-practices of useful routes and handlers that work with 2.1-OPs.
class Standard < Protocol
Expand Down Expand Up @@ -113,7 +105,6 @@ def self.extension_for_terminus_handler
[[Trailblazer::Activity::TaskWrap::Pipeline.method(:insert_after), "task_wrap.call_task", ["endpoint.end_signal", method(:terminus_handler)]]]
end
end

end
end
end