trailblazer-activity-dsl-linear 0.5.0 → 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +1 -1
  3. data/CHANGES.md +52 -0
  4. data/Gemfile +3 -1
  5. data/README.md +9 -17
  6. data/lib/trailblazer/activity/dsl/linear/feature/merge.rb +36 -0
  7. data/lib/trailblazer/activity/dsl/linear/feature/patch.rb +40 -0
  8. data/lib/trailblazer/activity/dsl/linear/feature/variable_mapping/dsl.rb +281 -0
  9. data/lib/trailblazer/activity/dsl/linear/feature/variable_mapping/inherit.rb +38 -0
  10. data/lib/trailblazer/activity/dsl/linear/feature/variable_mapping.rb +298 -0
  11. data/lib/trailblazer/activity/dsl/linear/helper/path.rb +106 -0
  12. data/lib/trailblazer/activity/dsl/linear/helper.rb +54 -128
  13. data/lib/trailblazer/activity/dsl/linear/normalizer/terminus.rb +92 -0
  14. data/lib/trailblazer/activity/dsl/linear/normalizer.rb +194 -77
  15. data/lib/trailblazer/activity/dsl/linear/sequence/builder.rb +47 -0
  16. data/lib/trailblazer/activity/dsl/linear/sequence/compiler.rb +72 -0
  17. data/lib/trailblazer/activity/dsl/linear/sequence/search.rb +58 -0
  18. data/lib/trailblazer/activity/dsl/linear/sequence.rb +34 -0
  19. data/lib/trailblazer/activity/dsl/linear/strategy.rb +116 -71
  20. data/lib/trailblazer/activity/dsl/linear/version.rb +1 -1
  21. data/lib/trailblazer/activity/dsl/linear.rb +21 -177
  22. data/lib/trailblazer/activity/fast_track.rb +42 -53
  23. data/lib/trailblazer/activity/path.rb +52 -127
  24. data/lib/trailblazer/activity/railway.rb +48 -68
  25. data/trailblazer-activity-dsl-linear.gemspec +3 -2
  26. metadata +41 -13
  27. data/lib/trailblazer/activity/dsl/linear/compiler.rb +0 -70
  28. data/lib/trailblazer/activity/dsl/linear/state.rb +0 -63
  29. data/lib/trailblazer/activity/dsl/linear/variable_mapping.rb +0 -240
@@ -8,108 +8,153 @@ module Trailblazer
8
8
  # provides DSL inheritance
9
9
  # provides run-time {call}
10
10
  # maintains the {state} with {seq} and normalizer options
11
- module Strategy
12
- def initialize!(state)
13
- @state = state
14
-
15
- recompile_activity!(@state.to_h[:sequence])
16
- end
11
+ # This could be a class but we decided to leave it as a module that then gets
12
+ # extended into {Path} and friends. This won't trigger the inheritance (because)
13
+ # there is nothing to inherit.
14
+ class Strategy
15
+ extend Linear::Helper # import {Subprocess()} and friends as class methods. creates shortcuts to {Strategy.Output} etc.
16
+ include Linear::Helper::Constants
17
+
18
+ class << self
19
+ def initialize!(state)
20
+ @state = state
21
+ end
17
22
 
18
- def inherited(inheriter)
19
- super
23
+ def inherited(inheriter)
24
+ super
20
25
 
21
- # inherits the {@sequence}, and options.
22
- inheriter.initialize!(@state.copy)
23
- end
26
+ # Inherits the {State:sequencer} and other options without recomputing anything.
27
+ inheriter.initialize!(@state.copy)
28
+ end
24
29
 
25
- # Called from {#step} and friends.
26
- def self.task_for!(state, type, task, options={}, &block)
27
- options = options.merge(dsl_track: type)
30
+ # @public
31
+ # We forward `step` to the Dsl (State) object.
32
+ # Recompiling the activity/sequence is a matter specific to Strategy (Railway etc).
33
+ def step(*args, &block); recompile_activity_for(:step, *args, &block); end
34
+ def terminus(*args); recompile_activity_for(:terminus, *args); end
28
35
 
29
- # {#update_sequence} is the only way to mutate the state instance.
30
- state.update_sequence do |sequence:, normalizers:, normalizer_options:, fields:|
31
- # Compute the sequence rows.
32
- options = normalizers.(type, normalizer_options: normalizer_options, options: task, user_options: options.merge(sequence: sequence))
36
+ private def recompile_activity_for(type, *args, &block)
37
+ sequence = apply_step_on_sequence_builder(type, *args, &block)
33
38
 
34
- sequence = Activity::DSL::Linear::DSL.apply_adds_from_dsl(sequence, **options)
39
+ recompile!(sequence)
35
40
  end
36
- end
37
41
 
38
- # @public
39
- private def step(*args, &block)
40
- recompile_activity_for(:step, *args, &block)
41
- end
42
+ # TODO: make {rescue} optional, only in dev mode.
43
+ # @return Sequence
44
+ private def apply_step_on_sequence_builder(type, arg, options={}, &block)
45
+ return Sequence::Builder.(type, arg, options,
46
+ sequence: @state.get(:sequence),
47
+ normalizers: @state.get(:normalizers),
42
48
 
43
- private def recompile_activity_for(type, *args, &block)
44
- args = forward_block(args, block)
49
+ normalizer_options: @state.get(:normalizer_options),
45
50
 
46
- seq = @state.send(type, *args)
51
+ &block
52
+ )
47
53
 
48
- recompile_activity!(seq)
49
- rescue Sequence::IndexError
50
- # re-raise this exception with activity class prepended
51
- # to the message this time.
52
- raise $!, "#{self}:#{$!.message}"
53
- end
54
+ rescue Activity::Adds::IndexError
55
+ # re-raise this exception with activity class prepended
56
+ # to the message this time.
57
+ raise $!, "#{self}:#{$!.message}"
58
+ end
54
59
 
55
- private def recompile_activity!(seq)
56
- schema = Compiler.(seq)
60
+ private def recompile_activity(sequence)
61
+ schema = Sequence::Compiler.(sequence)
62
+ Activity.new(schema)
63
+ end
57
64
 
58
- @activity = Activity.new(schema)
59
- end
65
+ # DISCUSS: this should be the only way to "update" anything on state.
66
+ def recompile!(sequence)
67
+ activity = recompile_activity(sequence)
60
68
 
61
- private def forward_block(args, block)
62
- options = args[1]
69
+ @state.update!(:sequence) { |*| sequence }
70
+ @state.update!(:activity) { |*| activity }
71
+ end
63
72
 
64
- return args unless options.is_a?(Hash)
73
+ # Used only once per strategy class body.
74
+ def compile_strategy!(strategy, **options)
75
+ options = strategy.OptionsForSequenceBuilder(**options)
65
76
 
66
- # FIXME: doesn't account {task: <>} and repeats logic from Normalizer.
77
+ compile_strategy_for!(**options)
78
+ end
67
79
 
68
- # DISCUSS: THIS SHOULD BE DONE IN DSL.Path() which is stateful! the block forwarding should be the only thing happening here!
69
- evaluated_options =
70
- options.find_all { |k,v| v.is_a?(BlockProxy) }.collect do |output, proxy|
71
- shared_options = {step_interface_builder: @state.instance_variable_get(:@normalizer_options)[:step_interface_builder]} # FIXME: how do we know what to pass on and what not?
80
+ def compile_strategy_for!(sequence:, normalizers:, **normalizer_options)
81
+ @state.update!(:normalizers) { normalizers } # immutable
82
+ @state.update!(:normalizer_options) { normalizer_options } # immutable
72
83
 
73
- [output, Linear.Path(**shared_options, **proxy.options, &(proxy.block || block))] # FIXME: the || sucks.
84
+ recompile!(sequence)
74
85
  end
75
86
 
76
- evaluated_options = Hash[evaluated_options]
87
+ # Mainly used for introspection.
88
+ def to_h
89
+ activity = @state.get(:activity)
77
90
 
78
- return args[0], options.merge(evaluated_options)
79
- end
91
+ activity.to_h.to_h.merge(
92
+ activity: activity,
93
+ sequence: @state.get(:sequence),
94
+ )
95
+ end
80
96
 
81
- def Path(**options, &block) # syntactically, we can't access the {do ... end} block here.
82
- BlockProxy.new(options, block)
83
- end
97
+ # @Runtime
98
+ # Injects {:exec_context} so that {:instance_method}s work.
99
+ def call(args, **circuit_options)
100
+ activity = @state.get(:activity)
84
101
 
85
- BlockProxy = Struct.new(:options, :block)
102
+ activity.(
103
+ args,
104
+ **circuit_options.merge(exec_context: new)
105
+ )
106
+ end
86
107
 
87
- private def merge!(activity)
88
- old_seq = @state.instance_variable_get(:@sequence) # TODO: fixme
89
- new_seq = activity.instance_variable_get(:@state).instance_variable_get(:@sequence) # TODO: fix the interfaces
108
+ def invoke(*args)
109
+ TaskWrap.invoke(self, *args)
110
+ end
111
+ end # class << self
112
+ # FIXME: do we want class << self?!
90
113
 
91
- seq = Linear.Merge(old_seq, new_seq, end_id: "End.success")
114
+ module DSL
115
+ module_function
92
116
 
93
- @state.instance_variable_set(:@sequence, seq) # FIXME: hate this so much.
94
- end
117
+ def start_sequence(wirings: [])
118
+ start_default = Activity::Start.new(semantic: :default)
119
+ start_event = Linear::Sequence.create_row(task: start_default, id: "Start.default", magnetic_to: nil, wirings: wirings)
120
+ _sequence = Linear::Sequence[start_event]
121
+ end
95
122
 
96
- def to_h
97
- @activity.to_h.to_h.merge(activity: @activity)
98
- end
123
+ def Build(strategy, **options, &block)
124
+ Class.new(strategy) do
125
+ compile_strategy!(strategy::DSL, normalizers: @state.get(:normalizers), **options)
99
126
 
100
- # Injects {:exec_context} so that {:instance_method}s work.
101
- def call(args, **circuit_options)
102
- @activity.(
103
- args,
104
- **circuit_options.merge(exec_context: new)
105
- )
106
- end
127
+ class_exec(&block) if block_given?
128
+ end
129
+ end
130
+ end # DSL
107
131
 
108
- def invoke(*args)
109
- TaskWrap.invoke(self, *args)
132
+ # FIXME: move to State#dup
133
+ def self.copy(value, **) # DISCUSS: should that be here?
134
+ value.copy
110
135
  end
136
+
137
+ require_relative "feature/merge"
138
+ extend Merge::DSL # {Strategy.merge!}
139
+
140
+ state = Declarative::State(
141
+ normalizers: [nil, {}], # immutable
142
+ normalizer_options: [nil, {}], # immutable
143
+
144
+ sequence: [nil, {}], # when inherited, call #dup
145
+ activity: [nil, {}], # when inherited, call #dup
146
+
147
+ fields: [Hash.new, {}],
148
+ )
149
+
150
+ initialize!(state) # build an empty State instance that can be copied and recompiled.
151
+ # override :sequencer, :sequence, :activity
152
+ # This is done in every subclass.
153
+ recompile!(DSL.start_sequence)
111
154
  end # Strategy
112
155
  end
113
156
  end
114
157
  end
115
158
  end
159
+
160
+
@@ -3,7 +3,7 @@ module Trailblazer
3
3
  module Activity
4
4
  module DSL
5
5
  module Linear
6
- VERSION = "0.5.0"
6
+ VERSION = "1.0.0.beta1"
7
7
  end
8
8
  end
9
9
  end
@@ -1,4 +1,5 @@
1
1
  require "trailblazer-activity"
2
+ require "trailblazer/declarative"
2
3
 
3
4
  class Trailblazer::Activity
4
5
  module DSL
@@ -6,193 +7,36 @@ class Trailblazer::Activity
6
7
  #
7
8
  # Produces {Implementation} and {Intermediate}.
8
9
  module Linear
9
- module_function
10
-
11
- # {Sequence} consists of rows.
12
- # {Sequence row} consisting of {[magnetic_to, task, connections_searches, data]}.
13
- class Sequence < Array
14
- # Return {Sequence row} consisting of {[magnetic_to, task, connections_searches, data]}.
15
- def self.create_row(task:, magnetic_to:, wirings:, **options)
16
- [
17
- magnetic_to,
18
- task,
19
- wirings,
20
- options # {id: "Start.success"}
21
- ]
22
- end
23
-
24
- # @returns Sequence New sequence instance
25
- # TODO: name it {apply_adds or something}
26
- def self.insert_row(sequence, row:, insert:)
27
- insert_function, *args = insert
28
-
29
- insert_function.(sequence, [row], *args)
30
- end
31
-
32
- def self.apply_adds(sequence, adds)
33
- adds.each do |add|
34
- sequence = insert_row(sequence, **add)
35
- end
36
-
37
- sequence
38
- end
39
-
40
- class IndexError < IndexError
41
- attr_reader :step_id
42
-
43
- def initialize(sequence, step_id)
44
- @step_id = step_id
45
- valid_ids = sequence.collect{ |row| row[3][:id].inspect }
46
-
47
- message = "\n" \
48
- "\e[31m#{@step_id.inspect} is not a valid step ID. Did you mean any of these ?\e[0m\n" \
49
- "\e[32m#{valid_ids.join("\n")}\e[0m"
50
-
51
- super(message)
52
- end
53
- end
54
- end
55
-
56
- # Sequence
57
- module Search
58
- module_function
59
-
60
- # From this task onwards, find the next task that's "magnetic to" {target_color}.
61
- # Note that we only go forward, no back-references are done here.
62
- def Forward(output, target_color)
63
- ->(sequence, me) do
64
- target_seq_row = find_in_range(sequence[sequence.index(me)+1..-1], target_color)
65
-
66
- return output, target_seq_row
67
- end
68
- end
69
-
70
- # Tries to find a track colored step by doing a Forward-search, first, then wraps around going
71
- # through all steps from sequence start to self.
72
- def WrapAround(output, target_color)
73
- ->(sequence, me) do
74
- my_index = sequence.index(me)
75
- # First, try all elements after me, then go through the elements preceding myself.
76
- wrapped_range = sequence[my_index+1..-1] + sequence[0..my_index-1]
77
-
78
- target_seq_row = find_in_range(wrapped_range, target_color)
79
-
80
- return output, target_seq_row
81
- end
82
- end
83
-
84
- def Noop(output)
85
- ->(sequence, me) do
86
- return output, [nil,nil,nil,{}] # FIXME
87
- end
88
- end
89
-
90
- # Find the seq_row with {id} and connect the current node to it.
91
- def ById(output, id)
92
- ->(sequence, me) do
93
- index = Insert.find_index(sequence, id) or return output, sequence[0] # FIXME # or raise "Couldn't find {#{id}}"
94
- target_seq_row = sequence[index]
95
-
96
- return output, target_seq_row
97
- end
98
- end
99
-
100
- # @private
101
- def find_in_range(range, target_color)
102
- _target_seq_row = range.find { |seq_row| seq_row[0] == target_color }
103
- end
104
- end # Search
105
-
106
- # Sequence
107
- # Functions to mutate the Sequence by inserting, replacing, or deleting tasks.
108
- # These functions are called in {insert_task}
10
+ # TODO: remove this deprecation for 1.1.
109
11
  module Insert
110
- module_function
111
-
112
- # Append {new_row} after {insert_id}.
113
- def Append(sequence, new_rows, insert_id)
114
- index, sequence = find(sequence, insert_id)
115
-
116
- sequence.insert(index+1, *new_rows)
117
- end
118
-
119
- # Insert {new_rows} before {insert_id}.
120
- def Prepend(sequence, new_rows, insert_id)
121
- index, sequence = find(sequence, insert_id)
122
-
123
- sequence.insert(index, *new_rows)
124
- end
125
-
126
- def Replace(sequence, new_rows, insert_id)
127
- index, sequence = find(sequence, insert_id)
12
+ def self.method(name)
13
+ warn "[Trailblazer] Using `Trailblazer::Activity::DSL::Linear::Insert.method(:#{name})` is deprecated.
14
+ Please use `Trailblazer::Activity::Adds::Insert.method(:#{name})`."
128
15
 
129
- sequence[index], _ = *new_rows # TODO: replace and insert remaining, if any.
130
- sequence
16
+ Trailblazer::Activity::Adds::Insert.method(name)
131
17
  end
132
-
133
- def Delete(sequence, _, insert_id)
134
- index, sequence = find(sequence, insert_id)
135
-
136
- sequence.delete(sequence[index])
137
- sequence
138
- end
139
-
140
- # @private
141
- def find_index(sequence, insert_id)
142
- sequence.find_index { |seq_row| seq_row[3][:id] == insert_id } # TODO: optimize id location!
143
- end
144
-
145
- def find(sequence, insert_id)
146
- index = find_index(sequence, insert_id) or raise Sequence::IndexError.new(sequence, insert_id)
147
-
148
- return index, sequence.clone # Ruby doesn't have an easy way to avoid mutating arrays :(
149
- end
150
- end
151
-
152
- def Merge(old_seq, new_seq, end_id: "End.success") # DISCUSS: also Insert
153
- new_seq = strip_start_and_ends(new_seq, end_id: end_id)
154
-
155
- _seq = Insert.Prepend(old_seq, new_seq, end_id)
156
18
  end
157
- def strip_start_and_ends(seq, end_id:) # TODO: introduce Merge namespace?
158
- cut_off_index = end_id.nil? ? seq.size : Insert.find_index(seq, end_id) # find the "first" end.
159
-
160
- seq[1..cut_off_index-1]
161
- end
162
-
163
- module DSL
164
- module_function
165
-
166
- # Insert the task into the sequence using the {sequence_insert} strategy.
167
- # @return Sequence sequence after applied insertion
168
- # FIXME: DSL for strategies
169
- def insert_task(sequence, sequence_insert:, **options)
170
- new_row = Sequence.create_row(**options)
171
-
172
- # {sequence_insert} is usually a function such as {Linear::Insert::Append} and its arguments.
173
- _seq = Sequence.insert_row(sequence, row: new_row, insert: sequence_insert)
174
- end
175
-
176
- # Add one or several rows to the {sequence}.
177
- # This is usually called from DSL methods such as {step}.
178
- def apply_adds_from_dsl(sequence, sequence_insert:, adds:, **options)
179
- # This is the ADDS for the actual task.
180
- task_add = {row: Sequence.create_row(**options), insert: sequence_insert} # Linear::Insert.method(:Prepend), end_id
181
-
182
- Sequence.apply_adds(sequence, [task_add] + adds)
183
- end
184
- end # DSL
185
-
186
- end
19
+ end # Linear
187
20
  end
188
21
  end
189
22
 
23
+ require "trailblazer/activity/dsl/linear/sequence"
24
+ require "trailblazer/activity/dsl/linear/sequence/builder"
25
+ require "trailblazer/activity/dsl/linear/sequence/search"
26
+ require "trailblazer/activity/dsl/linear/sequence/compiler"
190
27
  require "trailblazer/activity/dsl/linear/normalizer"
191
- require "trailblazer/activity/dsl/linear/state"
28
+ require "trailblazer/activity/dsl/linear/normalizer/terminus"
192
29
  require "trailblazer/activity/dsl/linear/helper"
30
+ require "trailblazer/activity/dsl/linear/helper/path"
193
31
  require "trailblazer/activity/dsl/linear/strategy"
194
- require "trailblazer/activity/dsl/linear/compiler"
195
32
  require "trailblazer/activity/path"
196
33
  require "trailblazer/activity/railway"
197
34
  require "trailblazer/activity/fast_track"
198
- require "trailblazer/activity/dsl/linear/variable_mapping"
35
+ require "trailblazer/activity/dsl/linear/feature/variable_mapping"
36
+ require "trailblazer/activity/dsl/linear/feature/variable_mapping/dsl"
37
+ require "trailblazer/activity/dsl/linear/feature/patch"
38
+
39
+ # feature/variable_mapping
40
+ Trailblazer::Activity::DSL::Linear::VariableMapping.extend!(Trailblazer::Activity::Path, :step)
41
+ Trailblazer::Activity::DSL::Linear::VariableMapping.extend!(Trailblazer::Activity::Railway, :step, :pass, :fail)
42
+ Trailblazer::Activity::DSL::Linear::VariableMapping.extend!(Trailblazer::Activity::FastTrack, :step, :pass, :fail)
@@ -1,61 +1,52 @@
1
1
  module Trailblazer
2
2
  class Activity
3
- def self.FastTrack(options)
4
- Class.new(FastTrack) do
5
- initialize!(Railway::DSL::State.new(**FastTrack::DSL.OptionsForState(**options)))
6
- end
7
- end
8
-
9
- # Implementation module that can be passed to `Activity()`.
10
- class FastTrack
11
- Linear = Activity::DSL::Linear
3
+ # Implementation of the "FastTrack" layout that is also used for `Operation`.
4
+ class FastTrack < Activity::DSL::Linear::Strategy
12
5
 
13
6
  # Signals
14
7
  FailFast = Class.new(Signal)
15
8
  PassFast = Class.new(Signal)
16
9
 
17
10
  module DSL
18
- module_function
19
-
20
- def normalizer
21
- step_options(Trailblazer::Activity::Railway::DSL.normalizer)
22
- end
11
+ Linear = Activity::DSL::Linear
23
12
 
24
- def normalizer_for_fail
25
- pipeline = step_options(Trailblazer::Activity::Railway::DSL.normalizer_for_fail)
13
+ module_function
26
14
 
27
- TaskWrap::Pipeline.prepend(
28
- pipeline,
29
- "path.wirings",
15
+ def Normalizer(base_normalizer=Trailblazer::Activity::Railway::DSL.Normalizer())
16
+ Linear::Normalizer.prepend_to(
17
+ base_normalizer,
18
+ "activity.wirings",
30
19
 
31
20
  {
32
- "fast_track.fail_fast_option_for_fail" => Linear::Normalizer.Task(method(:fail_fast_option_for_fail)),
21
+ "fast_track.pass_fast_option" => Linear::Normalizer.Task(method(:pass_fast_option)),
22
+ "fast_track.fail_fast_option" => Linear::Normalizer.Task(method(:fail_fast_option)),
23
+ "fast_track.fast_track_option" => Linear::Normalizer.Task(method(:fast_track_option)),
33
24
  }
34
25
  )
35
26
  end
36
27
 
37
- def normalizer_for_pass
38
- pipeline = step_options(Trailblazer::Activity::Railway::DSL.normalizer_for_pass)
28
+ def NormalizerForFail
29
+ pipeline = Normalizer(Railway::DSL.NormalizerForFail())
39
30
 
40
- TaskWrap::Pipeline.prepend(
31
+ Linear::Normalizer.prepend_to(
41
32
  pipeline,
42
- "path.wirings",
33
+ "activity.wirings",
43
34
 
44
35
  {
45
- "fast_track.pass_fast_option_for_pass" => Linear::Normalizer.Task(method(:pass_fast_option_for_pass)),
36
+ "fast_track.fail_fast_option_for_fail" => Linear::Normalizer.Task(method(:fail_fast_option_for_fail)),
46
37
  }
47
38
  )
48
39
  end
49
40
 
50
- def step_options(pipeline)
51
- TaskWrap::Pipeline.prepend(
41
+ def NormalizerForPass
42
+ pipeline = Normalizer(Railway::DSL.NormalizerForPass())
43
+
44
+ Linear::Normalizer.prepend_to(
52
45
  pipeline,
53
- "path.wirings",
46
+ "activity.wirings",
54
47
 
55
48
  {
56
- "fast_track.pass_fast_option" => Linear::Normalizer.Task(method(:pass_fast_option)),
57
- "fast_track.fail_fast_option" => Linear::Normalizer.Task(method(:fail_fast_option)),
58
- "fast_track.fast_track_option" => Linear::Normalizer.Task(method(:fast_track_option)),
49
+ "fast_track.pass_fast_option_for_pass" => Linear::Normalizer.Task(method(:pass_fast_option_for_pass)),
59
50
  }
60
51
  )
61
52
  end
@@ -106,7 +97,7 @@ module Trailblazer
106
97
  def merge_connections_for!(ctx, option_name, semantic, magnetic_to=option_name, connections:, **)
107
98
  return ctx unless ctx[option_name]
108
99
 
109
- ctx[:connections] = connections.merge(semantic => [Linear::Search.method(:Forward), magnetic_to])
100
+ ctx[:connections] = connections.merge(semantic => [Linear::Sequence::Search.method(:Forward), magnetic_to])
110
101
  ctx
111
102
  end
112
103
 
@@ -115,31 +106,28 @@ module Trailblazer
115
106
  ctx
116
107
  end
117
108
 
118
- def initial_sequence(initial_sequence:, fail_fast_end: Activity::End.new(semantic: :fail_fast), pass_fast_end: Activity::End.new(semantic: :pass_fast), **_o)
119
- sequence = initial_sequence
120
-
121
- sequence = Path::DSL.append_end(sequence, task: fail_fast_end, magnetic_to: :fail_fast, id: "End.fail_fast")
122
- sequence = Path::DSL.append_end(sequence, task: pass_fast_end, magnetic_to: :pass_fast, id: "End.pass_fast")
109
+ def initial_sequence(sequence:, fail_fast_end: Activity::End.new(semantic: :fail_fast), pass_fast_end: Activity::End.new(semantic: :pass_fast), **)
110
+ sequence = Path::DSL.append_terminus(sequence, fail_fast_end, magnetic_to: :fail_fast, id: "End.fail_fast", normalizers: Normalizers)
111
+ sequence = Path::DSL.append_terminus(sequence, pass_fast_end, magnetic_to: :pass_fast, id: "End.pass_fast", normalizers: Normalizers)
123
112
  end
124
113
 
125
- # This is slow and should be done only once at compile-time,
126
- # DISCUSS: maybe make this a function?
127
- # These are the normalizers for an {Activity}, to be injected into a State.
128
- Normalizers = Linear::State::Normalizer.new(
129
- step: Linear::Normalizer.activity_normalizer( FastTrack::DSL.normalizer ), # here, we extend the generic FastTrack::step_normalizer with the Activity-specific DSL
130
- fail: Linear::Normalizer.activity_normalizer( FastTrack::DSL.normalizer_for_fail ),
131
- pass: Linear::Normalizer.activity_normalizer( FastTrack::DSL.normalizer_for_pass ),
114
+ # Normalizer pipelines taking care of processing your DSL options.
115
+ Normalizers = Linear::Normalizer::Normalizers.new(
116
+ step: FastTrack::DSL.Normalizer(),
117
+ fail: FastTrack::DSL.NormalizerForFail(),
118
+ pass: FastTrack::DSL.NormalizerForPass(),
119
+ terminus: Linear::Normalizer::Terminus.Normalizer(),
132
120
  )
133
121
 
134
- def self.OptionsForState(normalizers: Normalizers, **options)
135
- options = Railway::DSL.OptionsForState(**options).
136
- merge(normalizers: normalizers)
122
+ def self.OptionsForSequenceBuilder(**options)
123
+
124
+ options = Railway::DSL.OptionsForSequenceBuilder(**options)
137
125
 
138
- initial_sequence = FastTrack::DSL.initial_sequence(**options)
126
+ initial_sequence = DSL.initial_sequence(**options)
139
127
 
140
128
  {
141
129
  **options,
142
- initial_sequence: initial_sequence,
130
+ sequence: initial_sequence,
143
131
  }
144
132
  end
145
133
  end # DSL
@@ -154,10 +142,11 @@ module Trailblazer
154
142
  end
155
143
  end
156
144
 
157
- include Activity::DSL::Linear::Helper
158
- extend Activity::DSL::Linear::Strategy
159
-
160
- initialize!(Railway::DSL::State.new(**DSL.OptionsForState()))
145
+ compile_strategy!(DSL, normalizers: DSL::Normalizers)
161
146
  end # FastTrack
147
+
148
+ def self.FastTrack(**options, &block)
149
+ Activity::DSL::Linear::Strategy::DSL.Build(FastTrack, **options, &block)
150
+ end
162
151
  end
163
152
  end