trailblazer-activity 0.4.2 → 0.4.3
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.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/CHANGES.md +7 -0
- data/README.md +1 -1
- data/inspeccccccccct.rb +19 -0
- data/lib/trailblazer/activity.rb +2 -1
- data/lib/trailblazer/activity/dsl/helper.rb +8 -0
- data/lib/trailblazer/activity/implementation/build_state.rb +1 -0
- data/lib/trailblazer/activity/implementation/path.rb +2 -34
- data/lib/trailblazer/activity/implementation/plan.rb +36 -0
- data/lib/trailblazer/activity/implementation/railway.rb +3 -3
- data/lib/trailblazer/activity/introspect.rb +20 -7
- data/lib/trailblazer/activity/magnetic.rb +2 -2
- data/lib/trailblazer/activity/magnetic/builder.rb +8 -15
- data/lib/trailblazer/activity/magnetic/builder/normalizer.rb +26 -26
- data/lib/trailblazer/activity/magnetic/builder/path.rb +10 -9
- data/lib/trailblazer/activity/magnetic/builder/railway.rb +4 -5
- data/lib/trailblazer/activity/magnetic/dsl.rb +6 -6
- data/lib/trailblazer/activity/magnetic/{dsl → structure}/alterations.rb +0 -0
- data/lib/trailblazer/activity/magnetic/structure/plus_poles.rb +92 -0
- data/lib/trailblazer/activity/structures.rb +2 -1
- data/lib/trailblazer/activity/task_builder.rb +5 -0
- data/lib/trailblazer/activity/task_wrap.rb +30 -24
- data/lib/trailblazer/activity/version.rb +1 -1
- metadata +6 -4
- data/lib/trailblazer/activity/magnetic/dsl/plus_poles.rb +0 -59
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b12275a2f1dfc9e9c90d7b3df76d2eab01db0964c453d61a23a307296cda2378
|
|
4
|
+
data.tar.gz: 93b881493ecec9eb50516cb1185ff1129c6fbc5efe478bc429604adae077c552
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7245451409ba95340e9a3ef5e9404df93b3e2f7aa9325fe2132bc45f4f7fbcd49370200dfe9532fb5fa8f4307fdd3f4c6eae480920927e232228361712ac8cef
|
|
7
|
+
data.tar.gz: a127529dea689958ff467558c6a373b37cfe0e2e2475b99b24f854488b672ff012cb8cccdfc3b02339e1b20e62eecbd92e5148fbe7e80ad5da7b8242e7f2c793
|
data/.travis.yml
CHANGED
data/CHANGES.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# 0.4.3
|
|
2
|
+
|
|
3
|
+
* Make `:outputs` the canonical way to define outputs, and not `:plus_poles`. The latter is computed by the DSL if not passed.
|
|
4
|
+
* Allow injecting `inspect` implementations into `Introspect` methods.
|
|
5
|
+
* Add `Nested`.
|
|
6
|
+
* Add `TaskBuilder::Task#to_s`.
|
|
7
|
+
|
|
1
8
|
# 0.4.2
|
|
2
9
|
|
|
3
10
|
* `End` is not a `Struct` so we can maintain more state, and are immutable.
|
data/README.md
CHANGED
|
@@ -4,7 +4,7 @@ The `activity` gem brings a light-weight DSL to define business processes, and t
|
|
|
4
4
|
|
|
5
5
|
A process is a set of arbitrary pieces of logic you define, chained together and put into a meaningful context by an activity. Activity lets you focus on the implementation of steps while Trailblazer takes care of the control flow.
|
|
6
6
|
|
|
7
|
-
Please find the [full documentation on the Trailblazer website](http://trailblazer.to/
|
|
7
|
+
Please find the [full documentation on the Trailblazer website](http://trailblazer.to/api-docs). [Note that the docs are WIP.]
|
|
8
8
|
|
|
9
9
|
## Example
|
|
10
10
|
|
data/inspeccccccccct.rb
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
|
|
2
|
+
module Inspect
|
|
3
|
+
def inspect
|
|
4
|
+
"nice view!"
|
|
5
|
+
end
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
module A
|
|
9
|
+
extend Inspect
|
|
10
|
+
|
|
11
|
+
def self.a
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# jruby 9.1.7
|
|
16
|
+
puts A.method(:a).inspect #=> #<Method: A.a>
|
|
17
|
+
# 2.5
|
|
18
|
+
puts A.method(:a).inspect #=> #<Method: nice view!.a>
|
|
19
|
+
|
data/lib/trailblazer/activity.rb
CHANGED
|
@@ -42,7 +42,7 @@ module Trailblazer
|
|
|
42
42
|
module DSLHelper
|
|
43
43
|
extend Forwardable
|
|
44
44
|
def_delegators :@builder, :Path
|
|
45
|
-
def_delegators DSL::Helper, :Output, :End
|
|
45
|
+
def_delegators DSL::Helper, :Output, :End, :Nested
|
|
46
46
|
|
|
47
47
|
def Path(*args, &block)
|
|
48
48
|
self[:builder].Path(*args, &block)
|
|
@@ -95,6 +95,7 @@ require "trailblazer/activity/config"
|
|
|
95
95
|
require "trailblazer/activity/implementation/build_state"
|
|
96
96
|
require "trailblazer/activity/implementation/interface"
|
|
97
97
|
require "trailblazer/activity/implementation/path"
|
|
98
|
+
require "trailblazer/activity/implementation/plan"
|
|
98
99
|
require "trailblazer/activity/implementation/railway"
|
|
99
100
|
require "trailblazer/activity/implementation/fast_track"
|
|
100
101
|
|
|
@@ -22,6 +22,7 @@ class Trailblazer::Activity < Module
|
|
|
22
22
|
return normalizer, options
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
# @api private
|
|
25
26
|
def self.build_state(normalizer, builder_class:, builder_options: {}, **options)
|
|
26
27
|
builder, adds, circuit, outputs = State.build(builder_class, normalizer, options.merge(builder_options))
|
|
27
28
|
|
|
@@ -11,45 +11,13 @@ module Trailblazer
|
|
|
11
11
|
{
|
|
12
12
|
builder_class: Magnetic::Builder::Path, # we use the Activity-based Normalizer
|
|
13
13
|
normalizer_class: Magnetic::Normalizer,
|
|
14
|
-
|
|
14
|
+
default_outputs: Magnetic::Builder::Path.default_outputs,
|
|
15
15
|
extension: [ Introspect.method(:add_introspection) ],
|
|
16
16
|
|
|
17
17
|
extend: [ DSL.def_dsl(:task) ],
|
|
18
18
|
}
|
|
19
19
|
end
|
|
20
|
-
|
|
21
|
-
def self.Plan()
|
|
22
|
-
Plan
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
module Plan
|
|
26
|
-
def self.extended(extended)
|
|
27
|
-
extended.singleton_class.send :attr_accessor, :record
|
|
28
|
-
extended.record = []
|
|
29
|
-
extended.extend(Methods)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
module Methods
|
|
33
|
-
def task(*args, &block)
|
|
34
|
-
record << [:task, args, block]
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def self.merge!(activity, plan)
|
|
39
|
-
plan.record.each { |(dsl_method, args, block)| activity.send(dsl_method, *args, &block) }
|
|
40
|
-
activity
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
# Creates a copy of the {activity} module and merges the {Plan} into it.
|
|
44
|
-
#
|
|
45
|
-
# @params activity [Activity] The activity to extend
|
|
46
|
-
# @params plan [Plan] The plan providing additional steps
|
|
47
|
-
# @return [Activity] A new, merged activity
|
|
48
|
-
def self.merge(activity, plan)
|
|
49
|
-
merge!(activity.clone, plan)
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
end
|
|
20
|
+
end # Path
|
|
53
21
|
end
|
|
54
22
|
end
|
|
55
23
|
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module Trailblazer
|
|
2
|
+
class Activity::Path < Activity
|
|
3
|
+
def self.Plan()
|
|
4
|
+
Plan
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
module Plan
|
|
8
|
+
def self.extended(extended)
|
|
9
|
+
extended.singleton_class.send :attr_accessor, :record
|
|
10
|
+
extended.record = []
|
|
11
|
+
extended.extend(Methods)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
module Methods
|
|
15
|
+
def task(*args, &block)
|
|
16
|
+
record << [:task, args, block]
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.merge!(activity, plan)
|
|
21
|
+
plan.record.each { |(dsl_method, args, block)| activity.send(dsl_method, *args, &block) }
|
|
22
|
+
activity
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Creates a copy of the {activity} module and merges the {Plan} into it.
|
|
26
|
+
#
|
|
27
|
+
# @params activity [Activity] The activity to extend
|
|
28
|
+
# @params plan [Plan] The plan providing additional steps
|
|
29
|
+
# @return [Activity] A new, merged activity
|
|
30
|
+
def self.merge(activity, plan)
|
|
31
|
+
merge!(activity.clone, plan)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
@@ -8,9 +8,9 @@ module Trailblazer
|
|
|
8
8
|
class Railway < Activity
|
|
9
9
|
def self.config
|
|
10
10
|
Path.config.merge(
|
|
11
|
-
builder_class:
|
|
12
|
-
|
|
13
|
-
extend:
|
|
11
|
+
builder_class: Magnetic::Builder::Railway,
|
|
12
|
+
default_outputs: Magnetic::Builder::Railway.default_outputs,
|
|
13
|
+
extend: [ DSL.def_dsl(:step), DSL.def_dsl(:fail), DSL.def_dsl(:pass) ],
|
|
14
14
|
)
|
|
15
15
|
end
|
|
16
16
|
end
|
|
@@ -35,6 +35,11 @@ module Trailblazer
|
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
|
|
38
|
+
def self.inspect_task_builder(task)
|
|
39
|
+
proc = task.instance_variable_get(:@user_proc)
|
|
40
|
+
%{#<TaskBuilder{#{proc}}>}
|
|
41
|
+
end
|
|
42
|
+
|
|
38
43
|
# FIXME: clean up that shit below.
|
|
39
44
|
|
|
40
45
|
# render
|
|
@@ -42,14 +47,14 @@ module Trailblazer
|
|
|
42
47
|
circuit_hash( circuit.to_h[:map], **options )
|
|
43
48
|
end
|
|
44
49
|
|
|
45
|
-
def self.circuit_hash(circuit_hash, show_ids:false)
|
|
50
|
+
def self.circuit_hash(circuit_hash, show_ids:false, **options)
|
|
46
51
|
content =
|
|
47
52
|
circuit_hash.collect do |task, connections|
|
|
48
53
|
conns = connections.collect do |signal, target|
|
|
49
|
-
" {#{signal}} => #{
|
|
54
|
+
" {#{signal}} => #{inspect_with_matcher(target, **options)}"
|
|
50
55
|
end
|
|
51
56
|
|
|
52
|
-
[
|
|
57
|
+
[ inspect_with_matcher(task, **options), conns.join("\n") ]
|
|
53
58
|
end
|
|
54
59
|
|
|
55
60
|
content = content.join("\n")
|
|
@@ -60,7 +65,7 @@ module Trailblazer
|
|
|
60
65
|
|
|
61
66
|
def self.Ends(activity)
|
|
62
67
|
end_events = activity.to_h[:end_events]
|
|
63
|
-
ends = end_events.collect { |evt|
|
|
68
|
+
ends = end_events.collect { |evt| inspect_end(evt) }.join(",")
|
|
64
69
|
"[#{ends}]".gsub(/\d\d+/, "")
|
|
65
70
|
end
|
|
66
71
|
|
|
@@ -70,9 +75,17 @@ module Trailblazer
|
|
|
70
75
|
join("\n").gsub(/0x\w+/, "").gsub(/\d\d+/, "")
|
|
71
76
|
end
|
|
72
77
|
|
|
73
|
-
|
|
74
|
-
|
|
78
|
+
# If Ruby had pattern matching, this function wasn't necessary.
|
|
79
|
+
def self.inspect_with_matcher(task, inspect_task: method(:inspect_task), inspect_end: method(:inspect_end))
|
|
80
|
+
return inspect_task.(task) unless task.kind_of?(Trailblazer::Activity::End)
|
|
81
|
+
inspect_end.(task)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def self.inspect_task(task)
|
|
85
|
+
task.inspect
|
|
86
|
+
end
|
|
75
87
|
|
|
88
|
+
def self.inspect_end(task)
|
|
76
89
|
class_name = strip(task.class)
|
|
77
90
|
options = task.to_h
|
|
78
91
|
|
|
@@ -108,7 +121,7 @@ module Trailblazer
|
|
|
108
121
|
sequence.collect do |(magnetic_to, task, plus_poles)|
|
|
109
122
|
pluses = plus_poles.collect { |plus_pole| PlusPole(plus_pole) }
|
|
110
123
|
|
|
111
|
-
%{#{magnetic_to.inspect} ==> #{Activity::Introspect.
|
|
124
|
+
%{#{magnetic_to.inspect} ==> #{Activity::Introspect.inspect_with_matcher(task)}
|
|
112
125
|
#{pluses.empty? ? " []" : pluses.join("\n")}}
|
|
113
126
|
end.join("\n")
|
|
114
127
|
|
|
@@ -16,8 +16,8 @@ module Trailblazer
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
require "trailblazer/activity/magnetic/dsl"
|
|
19
|
-
require "trailblazer/activity/magnetic/
|
|
20
|
-
require "trailblazer/activity/magnetic/
|
|
19
|
+
require "trailblazer/activity/magnetic/structure/plus_poles"
|
|
20
|
+
require "trailblazer/activity/magnetic/structure/alterations"
|
|
21
21
|
|
|
22
22
|
require "trailblazer/activity/schema/dependencies"
|
|
23
23
|
|
|
@@ -15,6 +15,7 @@ module Trailblazer
|
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
+
# Called from Path/Railway/FastTrack, creates the specific {Builder} instance.
|
|
18
19
|
def self.Builder(implementation, normalizer, builder_options={})
|
|
19
20
|
builder = implementation.new(normalizer, builder_options.freeze).freeze # e.g. Path.new(...)
|
|
20
21
|
|
|
@@ -32,11 +33,14 @@ module Trailblazer
|
|
|
32
33
|
activity_adds + merged_adds
|
|
33
34
|
end
|
|
34
35
|
|
|
35
|
-
#
|
|
36
|
+
# DSL method to create a Path within an activity which is embedded.
|
|
37
|
+
#
|
|
38
|
+
# Output(:success) => Path() {}
|
|
36
39
|
def Path(*args)
|
|
37
40
|
Activity::DSL::Helper.Path(@normalizer, *args)
|
|
38
41
|
end
|
|
39
42
|
|
|
43
|
+
# Public top-level entry point.
|
|
40
44
|
def insert(name, task, options, &block)
|
|
41
45
|
normalizer = options[:normalizer] || @normalizer # DISCUSS: do this at a deeper point?
|
|
42
46
|
|
|
@@ -50,13 +54,12 @@ module Trailblazer
|
|
|
50
54
|
private
|
|
51
55
|
|
|
52
56
|
# Internal top-level entry point to add task(s) and connections.
|
|
57
|
+
# High level interface for DSL calls like ::task or ::step.
|
|
53
58
|
def insert_element(impl, polarizations, task, local_options, connection_options, sequence_options, &block)
|
|
54
59
|
adds, *returned_options = Builder.adds_for(polarizations, task, local_options, connection_options, sequence_options, &block)
|
|
55
60
|
end
|
|
56
61
|
|
|
57
62
|
# @return Adds
|
|
58
|
-
# High level interface for DSL calls like ::task or ::step.
|
|
59
|
-
# TODO: RETURN ALL OPTIONS
|
|
60
63
|
def self.adds_for(polarizations, task, local_options, connection_options, sequence_options, &block)
|
|
61
64
|
# go through all wiring options such as Output()=>:color.
|
|
62
65
|
polarizations_from_user_options, additional_adds = process_dsl_options(connection_options, local_options, &block)
|
|
@@ -75,7 +78,7 @@ module Trailblazer
|
|
|
75
78
|
# Low-level interface for DSL calls (e.g. Start, where "you know what you're doing")
|
|
76
79
|
# @private
|
|
77
80
|
def self.adds(task, polarizations, options, sequence_options, magnetic_to:nil, id:nil, plus_poles:, **) # DISCUSS: no :id ?
|
|
78
|
-
magnetic_to, plus_poles = apply_polarizations(
|
|
81
|
+
magnetic_to, plus_poles = PlusPoles.apply_polarizations(
|
|
79
82
|
polarizations,
|
|
80
83
|
magnetic_to,
|
|
81
84
|
plus_poles,
|
|
@@ -88,19 +91,9 @@ module Trailblazer
|
|
|
88
91
|
)
|
|
89
92
|
end
|
|
90
93
|
|
|
91
|
-
# Called once per DSL method call, e.g. ::step.
|
|
92
|
-
#
|
|
93
|
-
# The idea is to chain a bunch of PlusPoles transformations (and magnetic_to "transformations")
|
|
94
|
-
# for each DSL call, and thus realize things like path+railway+fast_track
|
|
95
|
-
def self.apply_polarizations(polarizations, magnetic_to, plus_poles, options)
|
|
96
|
-
polarizations.inject([magnetic_to, plus_poles]) do |args, pol|
|
|
97
|
-
magnetic, plus_poles = pol.(*args, options)
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
|
|
101
94
|
def self.Add(id, task, magnetic_to, plus_poles, options, sequence_options)
|
|
102
95
|
[
|
|
103
|
-
[ :add, [id, [ magnetic_to, task, plus_poles
|
|
96
|
+
[ :add, [id, [ magnetic_to, task, plus_poles ], sequence_options] ],
|
|
104
97
|
]
|
|
105
98
|
end
|
|
106
99
|
end # Builder
|
|
@@ -1,40 +1,33 @@
|
|
|
1
1
|
module Trailblazer
|
|
2
2
|
module Activity::Magnetic
|
|
3
|
-
#
|
|
3
|
+
# One {Normalizer} instance is called for every DSL call (step/pass/fail etc.) and normalizes/defaults
|
|
4
4
|
# the user options, such as setting `:id`, connecting the task's outputs or wrapping the user's
|
|
5
5
|
# task via {TaskBuilder::Binary} in order to translate true/false to `Right` or `Left`.
|
|
6
6
|
#
|
|
7
7
|
# The Normalizer sits in the `@builder`, which receives all DSL calls from the Operation subclass.
|
|
8
8
|
class Normalizer
|
|
9
|
-
def self.build(task_builder: Activity::TaskBuilder::Binary,
|
|
9
|
+
def self.build(task_builder: Activity::TaskBuilder::Binary, default_outputs: Builder::Path.default_outputs, pipeline: Pipeline, extension:[], **options)
|
|
10
10
|
return new(
|
|
11
|
-
|
|
12
|
-
extension:
|
|
13
|
-
task_builder:
|
|
14
|
-
pipeline:
|
|
11
|
+
default_outputs: default_outputs,
|
|
12
|
+
extension: extension,
|
|
13
|
+
task_builder: task_builder,
|
|
14
|
+
pipeline: pipeline,
|
|
15
15
|
), options
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
Activity.Output(Activity::Left, :failure) => nil,
|
|
23
|
-
)
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def initialize(task_builder:, default_plus_poles:, pipeline:, **options)
|
|
27
|
-
@task_builder = task_builder
|
|
28
|
-
@default_plus_poles = default_plus_poles
|
|
29
|
-
@pipeline = pipeline # TODO: test me.
|
|
18
|
+
def initialize(task_builder:, default_outputs:, pipeline:, **options)
|
|
19
|
+
@task_builder = task_builder
|
|
20
|
+
@default_outputs = default_outputs
|
|
21
|
+
@pipeline = pipeline # TODO: test me.
|
|
30
22
|
freeze
|
|
31
23
|
end
|
|
32
24
|
|
|
33
25
|
def call(task, options)
|
|
34
26
|
ctx = {
|
|
35
|
-
task:
|
|
36
|
-
|
|
37
|
-
|
|
27
|
+
task: task,
|
|
28
|
+
options: options,
|
|
29
|
+
task_builder: @task_builder,
|
|
30
|
+
default_outputs: @default_outputs,
|
|
38
31
|
}
|
|
39
32
|
|
|
40
33
|
signal, (ctx, ) = @pipeline.( [ctx] )
|
|
@@ -46,7 +39,7 @@ module Trailblazer
|
|
|
46
39
|
|
|
47
40
|
# :default_plus_poles is an injectable option.
|
|
48
41
|
module Pipeline
|
|
49
|
-
extend Trailblazer::Activity::Path( normalizer_class: DefaultNormalizer, plus_poles: Builder::Path.
|
|
42
|
+
extend Trailblazer::Activity::Path( normalizer_class: DefaultNormalizer, plus_poles: PlusPoles.new.merge( Builder::Path.default_outputs.values ) ) # FIXME: the DefaultNormalizer actually doesn't need Left.
|
|
50
43
|
|
|
51
44
|
def self.split_options( ctx, task:, options:, ** )
|
|
52
45
|
keywords = extract_dsl_keywords(options)
|
|
@@ -84,11 +77,18 @@ module Trailblazer
|
|
|
84
77
|
end
|
|
85
78
|
end
|
|
86
79
|
|
|
87
|
-
#
|
|
88
|
-
|
|
80
|
+
# :outputs passed: I know what I want to have connected.
|
|
81
|
+
# no :outputs: use default_outputs
|
|
82
|
+
# ALWAYS connect all outputs to their semantic-color.
|
|
83
|
+
|
|
84
|
+
# Create the `plus_poles: <PlusPoles>` tuple where the PlusPoles instance will act as the interface
|
|
85
|
+
# to rewire or add connections for the DSL.
|
|
86
|
+
def self.initialize_plus_poles( ctx, local_options:, default_outputs:, ** )
|
|
87
|
+
outputs = local_options[:outputs] || default_outputs
|
|
88
|
+
|
|
89
89
|
ctx[:local_options] =
|
|
90
90
|
{
|
|
91
|
-
plus_poles:
|
|
91
|
+
plus_poles: PlusPoles.initial(outputs),
|
|
92
92
|
}
|
|
93
93
|
.merge(local_options)
|
|
94
94
|
end
|
|
@@ -96,7 +96,7 @@ module Trailblazer
|
|
|
96
96
|
task Activity::TaskBuilder::Binary.( method(:normalize_for_macro) ), id: "normalize_for_macro"
|
|
97
97
|
task Activity::TaskBuilder::Binary.( method(:split_options) ), id: "split_options"
|
|
98
98
|
task Activity::TaskBuilder::Binary.( method(:normalize_extension_option) ), id: "normalize_extension_option"
|
|
99
|
-
task Activity::TaskBuilder::Binary.( method(:
|
|
99
|
+
task Activity::TaskBuilder::Binary.( method(:initialize_plus_poles) ), id: "initialize_plus_poles"
|
|
100
100
|
# task ->((ctx, _), **) { pp ctx; [Activity::Right, [ctx, _]] }
|
|
101
101
|
end
|
|
102
102
|
end # Normalizer
|
|
@@ -20,15 +20,16 @@ module Trailblazer
|
|
|
20
20
|
return Path, polarizations, task, options, block
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
def self.
|
|
25
|
-
|
|
26
|
-
Activity.Output(
|
|
27
|
-
|
|
23
|
+
# @private Might be removed.
|
|
24
|
+
def self.default_outputs
|
|
25
|
+
{
|
|
26
|
+
success: Activity.Output(Activity::Right, :success),
|
|
27
|
+
# failure: Activity.Output(Activity::Left, :failure),
|
|
28
|
+
}
|
|
28
29
|
end
|
|
29
30
|
|
|
30
31
|
# @return [Adds] list of Adds instances that can be chained or added to an existing sequence.
|
|
31
|
-
def self.InitialAdds(track_color:raise, end_semantic:raise,
|
|
32
|
+
def self.InitialAdds(track_color:raise, end_semantic:raise, start_outputs: {success: self.default_outputs[:success]}, track_end: Activity.End(end_semantic), **)
|
|
32
33
|
|
|
33
34
|
builder_options={ track_color: track_color, end_semantic: end_semantic }
|
|
34
35
|
|
|
@@ -41,7 +42,7 @@ module Trailblazer
|
|
|
41
42
|
|
|
42
43
|
id: "Start.default",
|
|
43
44
|
magnetic_to: [],
|
|
44
|
-
plus_poles:
|
|
45
|
+
plus_poles: PlusPoles.initial(start_outputs), # FIXME: this is actually redundant with Normalizer
|
|
45
46
|
)
|
|
46
47
|
|
|
47
48
|
end_adds = adds(
|
|
@@ -59,14 +60,14 @@ module Trailblazer
|
|
|
59
60
|
start_adds + end_adds
|
|
60
61
|
end
|
|
61
62
|
|
|
62
|
-
def self.TaskPolarizations(track_color
|
|
63
|
+
def self.TaskPolarizations(track_color:, type: :task, **)
|
|
63
64
|
return [EndPolarization.new( track_color: track_color )] if type == :End # DISCUSS: should this dispatch be here?
|
|
64
65
|
|
|
65
66
|
[TaskPolarization.new( track_color: track_color )]
|
|
66
67
|
end
|
|
67
68
|
|
|
68
69
|
class TaskPolarization
|
|
69
|
-
def initialize(
|
|
70
|
+
def initialize(track_color:)
|
|
70
71
|
@track_color = track_color
|
|
71
72
|
end
|
|
72
73
|
|
|
@@ -22,11 +22,10 @@ module Trailblazer
|
|
|
22
22
|
return Railway, Railway.PassPolarizations(@builder_options), task, options, block
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
def self.
|
|
26
|
-
|
|
27
|
-
Activity.Output(Activity::
|
|
28
|
-
|
|
29
|
-
).freeze
|
|
25
|
+
def self.default_outputs
|
|
26
|
+
Path.default_outputs.merge(
|
|
27
|
+
:failure => Activity.Output(Activity::Left, :failure),
|
|
28
|
+
)
|
|
30
29
|
end
|
|
31
30
|
|
|
32
31
|
# Adds the End.failure end to the Path sequence.
|
|
@@ -28,30 +28,30 @@ module Trailblazer
|
|
|
28
28
|
# options:
|
|
29
29
|
# { DSL::Output[::Semantic] => target }
|
|
30
30
|
#
|
|
31
|
-
def call(id, options,
|
|
31
|
+
def call(id, options, plus_poles, &block)
|
|
32
32
|
polarization, adds =
|
|
33
33
|
options.
|
|
34
34
|
collect { |key, task|
|
|
35
35
|
# this method call is the only thing that really matters here. # TODO: make this transformation a bit more obvious.
|
|
36
|
-
process_tuple(id, key, task,
|
|
36
|
+
process_tuple(id, key, task, plus_poles, &block)
|
|
37
37
|
}.
|
|
38
38
|
inject([[],[]]) { |memo, (polarization, adds)| memo[0]<<polarization; memo[1]<<adds; memo }
|
|
39
39
|
|
|
40
40
|
return polarization, adds.flatten(1)
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
def process_tuple(id, output, task,
|
|
44
|
-
output = output_for(output,
|
|
43
|
+
def process_tuple(id, output, task, plus_poles, &block)
|
|
44
|
+
output = output_for(output, plus_poles) if output.kind_of?(DSL::Output::Semantic)
|
|
45
45
|
|
|
46
46
|
if task.kind_of?(Activity::End)
|
|
47
47
|
new_edge = "#{id}-#{output.signal}"
|
|
48
48
|
|
|
49
49
|
[
|
|
50
50
|
Polarization.new( output: output, color: new_edge ),
|
|
51
|
-
[ [:add, [task.
|
|
51
|
+
[ [:add, [task.to_h[:semantic], [ [new_edge], task, [] ], group: :end]] ]
|
|
52
52
|
]
|
|
53
53
|
elsif task.is_a?(String) # let's say this means an existing step
|
|
54
|
-
new_edge = "#{output.signal}-#{task}"
|
|
54
|
+
new_edge = "#{id}-#{output.signal}-#{task}"
|
|
55
55
|
|
|
56
56
|
[
|
|
57
57
|
Polarization.new( output: output, color: new_edge ),
|
|
File without changes
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
module Trailblazer
|
|
2
|
+
module Activity::Magnetic
|
|
3
|
+
# A plus pole is associating an Output{:signal, :semantic} to a magnetic :color.
|
|
4
|
+
#
|
|
5
|
+
# When it comes to connecting tasks to each other, PlusPoles is the most important object
|
|
6
|
+
# here. When a task is added via the DSL, a PlusPoles is set up, and the DSL adds polarizations
|
|
7
|
+
# from the implementation and from the options (e.g. `Outputs(..) => ..`).
|
|
8
|
+
#
|
|
9
|
+
# These are then finalized and return the effective plus poles
|
|
10
|
+
|
|
11
|
+
# Polarization is one or multiple calls to PlusPoles
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# Output(:signal, :semantic) => :color
|
|
18
|
+
# add / merge
|
|
19
|
+
# change existing, => color
|
|
20
|
+
#
|
|
21
|
+
#
|
|
22
|
+
# Produces [ PlusPole, PlusPole, ] via `to_a`.
|
|
23
|
+
#
|
|
24
|
+
# @privat
|
|
25
|
+
# @note This is private until we know what we want.
|
|
26
|
+
class PlusPoles
|
|
27
|
+
def initialize(plus_poles={})
|
|
28
|
+
@plus_poles = plus_poles.freeze
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# merge( Activity::Magnetic.Output(Right, :success) => :success
|
|
32
|
+
def merge(output_to_color)
|
|
33
|
+
overrides = ::Hash[ output_to_color.collect { |output, color| [ output.semantic, [output, color] ] } ]
|
|
34
|
+
PlusPoles.new(@plus_poles.merge(overrides))
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def reverse_merge(output_to_color)
|
|
38
|
+
existing_colors = @plus_poles.values.collect { |pole_cfg| pole_cfg.last }
|
|
39
|
+
|
|
40
|
+
# filter all outputs with a color that already exists.
|
|
41
|
+
overrides = output_to_color.find_all { |output, color| !existing_colors.include?(color) }
|
|
42
|
+
merge(overrides)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def reconnect(semantic_to_color)
|
|
46
|
+
ary = semantic_to_color.collect do |semantic, color|
|
|
47
|
+
existing_output, _ = @plus_poles[semantic]
|
|
48
|
+
|
|
49
|
+
next unless existing_output
|
|
50
|
+
|
|
51
|
+
[ Activity.Output(existing_output.signal, existing_output.semantic), color ]
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
merge( ::Hash[ary.compact] )
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Compile one {PlusPoles} instance from all a sequence of {Polarization}s.
|
|
58
|
+
# This is usually called once per `step` DSL call.
|
|
59
|
+
#
|
|
60
|
+
# @api private
|
|
61
|
+
def self.apply_polarizations(polarizations, magnetic_to, plus_poles, options)
|
|
62
|
+
magnetic_to, plus_poles = polarizations.inject([magnetic_to, plus_poles]) do |args, pol|
|
|
63
|
+
magnetic_to, plus_poles = pol.(*args, options)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
return magnetic_to, plus_poles.to_a
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# The DSL is a series of transformations that yield in tasks with several PlusPole instances each.
|
|
70
|
+
#
|
|
71
|
+
# @api private
|
|
72
|
+
def to_a
|
|
73
|
+
@plus_poles.values.collect { |output, color| PlusPole.new(output, color) }
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Builds PlusPoles from { semantic => Output }, which, surprisingly, is exactly what Activity::outputs looks like.
|
|
77
|
+
# The plus pole's color is set to the output's semantic.
|
|
78
|
+
def self.from_outputs(outputs)
|
|
79
|
+
ary = outputs.collect { |semantic, output| [ output, semantic ] }
|
|
80
|
+
|
|
81
|
+
new.merge(::Hash[ary])
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# FIXME: should this be a hash or whatever?
|
|
85
|
+
#
|
|
86
|
+
# @return Hash All {Output}s mapped to their semantic: `{ Output(Right, :success) => :success }`
|
|
87
|
+
def self.initial(outputs)
|
|
88
|
+
new.merge(Hash[ outputs.collect { |semantic, output| [output, semantic] } ])
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module Trailblazer
|
|
2
2
|
class Activity < Module # End event is just another callable task.
|
|
3
|
-
# Builds an Activity::End instance.
|
|
3
|
+
# Builds an {Activity::End} instance.
|
|
4
4
|
def self.End(semantic)
|
|
5
5
|
End.new(semantic: semantic)
|
|
6
6
|
end
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
# semantic: the original "semantic" or role of the signal, such as :success. This usually comes from the activity hosting this output.
|
|
49
49
|
Output = Struct.new(:signal, :semantic)
|
|
50
50
|
|
|
51
|
+
# Builds an {Activity::Output} instance.
|
|
51
52
|
def self.Output(signal, color)
|
|
52
53
|
Output.new(signal, color).freeze
|
|
53
54
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
module Trailblazer
|
|
2
|
+
class Activity < Module
|
|
2
3
|
#
|
|
3
4
|
# Example with tracing:
|
|
4
5
|
#
|
|
@@ -8,39 +9,44 @@ class Trailblazer::Activity < Module
|
|
|
8
9
|
# |-- Call (call actual task) id: "task_wrap.call_task"
|
|
9
10
|
# |-- Trace.capture_return [optional]
|
|
10
11
|
# |-- Wrap::End
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
module TaskWrap
|
|
13
|
+
# The actual activity that implements the taskWrap.
|
|
14
|
+
def self.initial_activity
|
|
15
|
+
Module.new do
|
|
16
|
+
extend Trailblazer::Activity::Path(
|
|
17
|
+
name: "taskWrap",
|
|
18
|
+
normalizer_class: Magnetic::DefaultNormalizer,
|
|
19
|
+
plus_poles: Magnetic::PlusPoles.initial( :success => Magnetic::Builder::Path.default_outputs[:success] ) # DefaultNormalizer doesn't give us default PlusPoles.
|
|
20
|
+
)
|
|
16
21
|
|
|
17
|
-
|
|
22
|
+
task TaskWrap.method(:call_task), id: "task_wrap.call_task" # ::call_task is defined in task_wrap/call_task.
|
|
23
|
+
end
|
|
18
24
|
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
# Compute runtime arguments necessary to execute a taskWrap per task of the activity.
|
|
22
|
-
def self.arguments_for_call(activity, (options, flow_options), **circuit_options)
|
|
23
|
-
circuit_options = circuit_options.merge(
|
|
24
|
-
runner: TaskWrap::Runner,
|
|
25
|
-
wrap_runtime: circuit_options[:wrap_runtime] || {},
|
|
26
|
-
wrap_static: activity[:wrap_static] || {},
|
|
27
|
-
)
|
|
28
25
|
|
|
29
|
-
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
module NonStatic
|
|
26
|
+
# Compute runtime arguments necessary to execute a taskWrap per task of the activity.
|
|
33
27
|
def self.arguments_for_call(activity, (options, flow_options), **circuit_options)
|
|
34
28
|
circuit_options = circuit_options.merge(
|
|
35
29
|
runner: TaskWrap::Runner,
|
|
36
|
-
wrap_runtime: circuit_options[:wrap_runtime] || {},
|
|
37
|
-
wrap_static:
|
|
30
|
+
wrap_runtime: circuit_options[:wrap_runtime] || {},
|
|
31
|
+
wrap_static: activity[:wrap_static] || {},
|
|
38
32
|
)
|
|
39
33
|
|
|
40
34
|
return activity, [ options, flow_options ], circuit_options
|
|
41
35
|
end
|
|
42
|
-
end
|
|
43
36
|
|
|
44
|
-
|
|
37
|
+
module NonStatic
|
|
38
|
+
def self.arguments_for_call(activity, (options, flow_options), **circuit_options)
|
|
39
|
+
circuit_options = circuit_options.merge(
|
|
40
|
+
runner: TaskWrap::Runner,
|
|
41
|
+
wrap_runtime: circuit_options[:wrap_runtime] || {}, # FIXME:this sucks. (was:) this overwrites wrap_runtime from outside.
|
|
42
|
+
wrap_static: ::Hash.new(TaskWrap.initial_activity), # add a default static wrap.
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
return activity, [ options, flow_options ], circuit_options
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# better: MyClass < Activity(TaskWrap, ...)
|
|
50
|
+
end
|
|
45
51
|
end
|
|
46
52
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: trailblazer-activity
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.4.
|
|
4
|
+
version: 0.4.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Nick Sutterer
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2018-
|
|
11
|
+
date: 2018-02-02 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: hirb
|
|
@@ -112,6 +112,7 @@ files:
|
|
|
112
112
|
- NOTES_
|
|
113
113
|
- README.md
|
|
114
114
|
- Rakefile
|
|
115
|
+
- inspeccccccccct.rb
|
|
115
116
|
- lib/trailblazer-activity.rb
|
|
116
117
|
- lib/trailblazer/activity.rb
|
|
117
118
|
- lib/trailblazer/activity/config.rb
|
|
@@ -121,6 +122,7 @@ files:
|
|
|
121
122
|
- lib/trailblazer/activity/implementation/fast_track.rb
|
|
122
123
|
- lib/trailblazer/activity/implementation/interface.rb
|
|
123
124
|
- lib/trailblazer/activity/implementation/path.rb
|
|
125
|
+
- lib/trailblazer/activity/implementation/plan.rb
|
|
124
126
|
- lib/trailblazer/activity/implementation/railway.rb
|
|
125
127
|
- lib/trailblazer/activity/introspect.rb
|
|
126
128
|
- lib/trailblazer/activity/magnetic.rb
|
|
@@ -131,11 +133,11 @@ files:
|
|
|
131
133
|
- lib/trailblazer/activity/magnetic/builder/path.rb
|
|
132
134
|
- lib/trailblazer/activity/magnetic/builder/railway.rb
|
|
133
135
|
- lib/trailblazer/activity/magnetic/dsl.rb
|
|
134
|
-
- lib/trailblazer/activity/magnetic/dsl/alterations.rb
|
|
135
|
-
- lib/trailblazer/activity/magnetic/dsl/plus_poles.rb
|
|
136
136
|
- lib/trailblazer/activity/magnetic/finalizer.rb
|
|
137
137
|
- lib/trailblazer/activity/magnetic/generate.rb
|
|
138
138
|
- lib/trailblazer/activity/magnetic/merge.rb
|
|
139
|
+
- lib/trailblazer/activity/magnetic/structure/alterations.rb
|
|
140
|
+
- lib/trailblazer/activity/magnetic/structure/plus_poles.rb
|
|
139
141
|
- lib/trailblazer/activity/present.rb
|
|
140
142
|
- lib/trailblazer/activity/schema/dependencies.rb
|
|
141
143
|
- lib/trailblazer/activity/schema/sequence.rb
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
module Trailblazer
|
|
2
|
-
module Activity::Magnetic
|
|
3
|
-
module DSL
|
|
4
|
-
# Output(:signal, :semantic) => :color
|
|
5
|
-
# add / merge
|
|
6
|
-
# change existing, => color
|
|
7
|
-
#
|
|
8
|
-
# Mutable DSL datastructure for managing all PlusPoles for a particular task.
|
|
9
|
-
#
|
|
10
|
-
# Produces [ PlusPole, PlusPole, ] via `to_a`.
|
|
11
|
-
#
|
|
12
|
-
# @privat
|
|
13
|
-
# @note This is private until we know what we want.
|
|
14
|
-
class PlusPoles
|
|
15
|
-
def initialize(plus_poles={})
|
|
16
|
-
@plus_poles = plus_poles.freeze
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
# merge( Activity::Magnetic.Output(Right, :success) => :success
|
|
20
|
-
def merge(output_to_color)
|
|
21
|
-
overrides = ::Hash[ output_to_color.collect { |output, color| [ output.semantic, [output, color] ] } ]
|
|
22
|
-
PlusPoles.new(@plus_poles.merge(overrides))
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def reverse_merge(output_to_color)
|
|
26
|
-
existing_colors = @plus_poles.values.collect { |pole_cfg| pole_cfg.last }
|
|
27
|
-
|
|
28
|
-
overrides = output_to_color.find_all { |output, color| !existing_colors.include?(color) } # filter all outputs with a color that already exists.
|
|
29
|
-
merge(overrides)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def reconnect(semantic_to_color)
|
|
33
|
-
ary = semantic_to_color.collect do |semantic, color|
|
|
34
|
-
existing_output, _ = @plus_poles[semantic]
|
|
35
|
-
|
|
36
|
-
next unless existing_output
|
|
37
|
-
|
|
38
|
-
[ Activity.Output(existing_output.signal, existing_output.semantic), color ]
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
merge( ::Hash[ary.compact] )
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
# The DSL is a series of transformations that yield in tasks with several PlusPole instances each.
|
|
45
|
-
def to_a
|
|
46
|
-
@plus_poles.values.collect { |output, color| PlusPole.new(output, color) }
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
# Builds PlusPoles from { semantic => Output }, which, surprisingly, is exactly what Activity::outputs looks like.
|
|
50
|
-
# The plus pole's color is set to the output's semantic.
|
|
51
|
-
def self.from_outputs(outputs)
|
|
52
|
-
ary = outputs.collect { |semantic, output| [ output, semantic ] }
|
|
53
|
-
|
|
54
|
-
new.merge(::Hash[ary])
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|