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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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