Class: Trailblazer::Endpoint

Inherits:
Object
  • Object
show all
Defined in:
lib/trailblazer/endpoint.rb,
lib/trailblazer/endpoint/dsl.rb,
lib/trailblazer/endpoint/adapter.rb,
lib/trailblazer/endpoint/builder.rb,
lib/trailblazer/endpoint/options.rb,
lib/trailblazer/endpoint/version.rb,
lib/trailblazer/endpoint/protocol.rb,
lib/trailblazer/endpoint/controller.rb

Defined Under Namespace

Modules: Adapter, Controller, DSL, Handlers, Normalizer, Options Classes: Builder, Protocol

Constant Summary collapse

VERSION =
"0.0.10"

Class Method Summary collapse

Class Method Details

.advance_from_controller(endpoint, success_block:, failure_block:, protocol_failure_block:, **argument_options) ⇒ Object

FIXME: name will change! this is for controllers, only!



134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/trailblazer/endpoint.rb', line 134

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(
    endpoint,
    args[0], # [ctx, flow_options]

    success_block:          success_block,
    failure_block:          failure_block,
    protocol_failure_block: protocol_failure_block,
  )

  ctx
end

.arguments_for(domain_ctx:, flow_options:, circuit_options: {}, **endpoint_options) ⇒ Object

@ For WORKFLOW and operations. not sure this method will stay here.



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/trailblazer/endpoint.rb', line 111

def self.arguments_for(domain_ctx:, flow_options:, circuit_options: {}, **endpoint_options)
  # we don't have to create the Ctx wrapping explicitly here. this is done via `:input`.
  # domain_ctx      = Trailblazer::Context::IndifferentAccess.build(domain_ctx, {}, [domain_ctx, flow_options], circuit_options)

  [
    [
      {
          domain_ctx:                     domain_ctx, # DISCUSS: is this where {:resume_data} comes in?
          # process_model_class:            process_model_class,
          # process_model_from_resume_data: process_model_from_resume_data,
          # find_process_model:             find_process_model,
          # encrypted_resume_data:          encrypted_resume_data,

          # cipher_key:                     cipher_key,
          **endpoint_options,
      },
      flow_options
    ],
    circuit_options
  ]
end

.build(protocol:, adapter:, domain_activity:, scope_domain_ctx: true, protocol_block: ->(*) { Hash.new }, serialize: false, deserialize: false, find_process_model: false, deserialize_process_model_id_from_resume_data: false) ⇒ Object

Create an Trailblazer::Endpoint class with the provided adapter and protocol. This builder also sets up taskWrap filters around the domain_activity execution.



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/trailblazer/endpoint.rb', line 5

def self.build(protocol:, adapter:, domain_activity:, scope_domain_ctx: true, protocol_block: ->(*) { Hash.new },
  serialize: false, # TODO: plug-in, not hardcoded!
  deserialize: false,# TODO: plug-in, not hardcoded!
  find_process_model: false, # TODO: plug-in, not hardcoded!
  deserialize_process_model_id_from_resume_data: false # TODO: plug-in, not hardcoded!
  )
  # special considerations around the {domain_activity} and its taskWrap:
  #
  #  1. domain_ctx_filter (e.g. to filter {current_user})
  #  2. :input (scope {:domain_ctx})
  #  3. call (domain_activity)
  #  4. :output
  #  5. save return signal


  extensions_options = {
    extensions: [Trailblazer::Activity::TaskWrap::Extension(merge: Trailblazer::Endpoint::Protocol::Domain.extension_for_terminus_handler)],
  }

  # scoping: {:domain_ctx} becomes ctx
  extensions_options.merge!(Endpoint.options_for_scope_domain_ctx) if scope_domain_ctx # TODO: test flag

  app_protocol = build_protocol(protocol, domain_activity: domain_activity, extensions_options: extensions_options, protocol_block: protocol_block, serialize: serialize, deserialize: deserialize,
    find_process_model: find_process_model, deserialize_process_model_id_from_resume_data: deserialize_process_model_id_from_resume_data
    )

  # puts Trailblazer::Developer.render(app_protocol)

  Class.new(adapter) do
    step(Subprocess(app_protocol), {inherit: true, id: :protocol, replace: :protocol})
  end # app_adapter

end

.build_protocol(protocol, domain_activity:, extensions_options:, protocol_block:, serialize:, deserialize:, find_process_model:, deserialize_process_model_id_from_resume_data:) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/trailblazer/endpoint.rb', line 40

def self.build_protocol(protocol, domain_activity:, extensions_options:, protocol_block:, serialize:, deserialize:, find_process_model:, deserialize_process_model_id_from_resume_data:)
  Class.new(protocol) do
    if serialize
      Protocol::Controller.insert_serialize_steps!(self)
    end

    if deserialize
      Protocol::Controller.insert_deserialize_steps!(self)
    end

    if serialize || deserialize
      Protocol::Controller.insert_copy_to_domain_ctx!(self, {:resume_data => :resume_data})
    end

    if find_process_model
      Protocol::Controller.insert_find_process_model!(self, before: :policy) # TODO: test before: :policy
    end

    if deserialize_process_model_id_from_resume_data
      pass Protocol::Controller.method(:deserialize_process_model_id_from_resume_data), after: :deserialize_resume_data, magnetic_to: :deserialize, Output(:success) => Track(:deserialize)
    end

    step(Subprocess(domain_activity), {inherit: true, id: :domain_activity, replace: :domain_activity,

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

.options_for_scope_domain_ctxObject



72
73
74
75
76
77
# File 'lib/trailblazer/endpoint.rb', line 72

def self.options_for_scope_domain_ctx()
  {
    input:  ->(ctx, **) { ctx[:domain_ctx] }, # gets automatically Context()'ed.
    output: ->(domain_ctx, **) { {:domain_ctx => domain_ctx} }
  }
end

.with_or_etc(activity, args, failure_block:, success_block:, protocol_failure_block:, invoke: Trailblazer::Activity::TaskWrap.method(:invoke)) ⇒ Object

Runtime Invokes the endpoint for you and runs one of the three outcome blocks.



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/trailblazer/endpoint.rb', line 81

def self.with_or_etc(activity, args, failure_block:, success_block:, protocol_failure_block:, invoke: Trailblazer::Activity::TaskWrap.method(:invoke))
# def self.with_or_etc(activity, args, failure_block:, success_block:, protocol_failure_block:, invoke: Trailblazer::Developer.method(:wtf?))

  # args[1] = args[1].merge(focus_on: { variables: [:returned], steps: :invoke_workflow })

  # signal, (endpoint_ctx, _ ) = Trailblazer::Developer.wtf?(activity, args)
  signal, (endpoint_ctx, _ ) = invoke.call(activity, args) # translates to Trailblazer::Developer.wtf?(activity, args)

  # this ctx is passed to the controller block.
  block_ctx = endpoint_ctx[:domain_ctx].merge(endpoint_ctx: endpoint_ctx, signal: signal, errors: endpoint_ctx[:errors]) # DISCUSS: errors? status?

  # if signal < Trailblazer::Activity::End::Success
  adapter_terminus_semantic = signal.to_h[:semantic]

  executed_block =
    if adapter_terminus_semantic    == :success
      success_block
    elsif adapter_terminus_semantic == :fail_fast
      protocol_failure_block
    else
      failure_block
    end

  executed_block.(block_ctx, **block_ctx)

  # we return the original context???
  return signal, [endpoint_ctx]
end