trailblazer-activity 0.7.1 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop-https---raw-githubusercontent-com-trailblazer-meta-master-rubocop-yml +101 -0
  3. data/.rubocop.yml +4 -13
  4. data/.rubocop_todo.yml +474 -476
  5. data/.travis.yml +3 -2
  6. data/CHANGES.md +10 -0
  7. data/Gemfile +5 -4
  8. data/README.md +2 -0
  9. data/Rakefile +1 -1
  10. data/lib/trailblazer/activity.rb +29 -92
  11. data/lib/trailblazer/activity/circuit.rb +74 -0
  12. data/lib/trailblazer/activity/config.rb +4 -6
  13. data/lib/trailblazer/activity/introspect.rb +33 -129
  14. data/lib/trailblazer/activity/present.rb +14 -39
  15. data/lib/trailblazer/activity/schema.rb +13 -0
  16. data/lib/trailblazer/activity/schema/implementation.rb +10 -0
  17. data/lib/trailblazer/activity/schema/intermediate.rb +94 -0
  18. data/lib/trailblazer/activity/structures.rb +43 -43
  19. data/lib/trailblazer/activity/task_wrap.rb +29 -16
  20. data/lib/trailblazer/activity/task_wrap/call_task.rb +4 -4
  21. data/lib/trailblazer/activity/task_wrap/inject.rb +37 -0
  22. data/lib/trailblazer/activity/task_wrap/pipeline.rb +55 -0
  23. data/lib/trailblazer/activity/task_wrap/runner.rb +10 -19
  24. data/lib/trailblazer/activity/task_wrap/variable_mapping.rb +25 -97
  25. data/lib/trailblazer/activity/testing.rb +64 -22
  26. data/lib/trailblazer/activity/trace.rb +88 -41
  27. data/lib/trailblazer/activity/version.rb +4 -2
  28. data/trailblazer-activity.gemspec +5 -9
  29. metadata +18 -55
  30. data/lib/trailblazer/activity/dsl/add_task.rb +0 -22
  31. data/lib/trailblazer/activity/dsl/helper.rb +0 -68
  32. data/lib/trailblazer/activity/dsl/magnetic.rb +0 -36
  33. data/lib/trailblazer/activity/dsl/magnetic/builder.rb +0 -101
  34. data/lib/trailblazer/activity/dsl/magnetic/builder/default_normalizer.rb +0 -26
  35. data/lib/trailblazer/activity/dsl/magnetic/builder/fast_track.rb +0 -118
  36. data/lib/trailblazer/activity/dsl/magnetic/builder/normalizer.rb +0 -113
  37. data/lib/trailblazer/activity/dsl/magnetic/builder/path.rb +0 -105
  38. data/lib/trailblazer/activity/dsl/magnetic/builder/railway.rb +0 -97
  39. data/lib/trailblazer/activity/dsl/magnetic/builder/state.rb +0 -58
  40. data/lib/trailblazer/activity/dsl/magnetic/finalizer.rb +0 -51
  41. data/lib/trailblazer/activity/dsl/magnetic/generate.rb +0 -62
  42. data/lib/trailblazer/activity/dsl/magnetic/merge.rb +0 -16
  43. data/lib/trailblazer/activity/dsl/magnetic/process_options.rb +0 -76
  44. data/lib/trailblazer/activity/dsl/magnetic/structure/alterations.rb +0 -44
  45. data/lib/trailblazer/activity/dsl/magnetic/structure/plus_poles.rb +0 -85
  46. data/lib/trailblazer/activity/dsl/magnetic/structure/polarization.rb +0 -23
  47. data/lib/trailblazer/activity/dsl/record.rb +0 -11
  48. data/lib/trailblazer/activity/dsl/schema/dependencies.rb +0 -46
  49. data/lib/trailblazer/activity/dsl/schema/sequence.rb +0 -46
  50. data/lib/trailblazer/activity/dsl/strategy/build_state.rb +0 -32
  51. data/lib/trailblazer/activity/dsl/strategy/fast_track.rb +0 -24
  52. data/lib/trailblazer/activity/dsl/strategy/path.rb +0 -26
  53. data/lib/trailblazer/activity/dsl/strategy/plan.rb +0 -36
  54. data/lib/trailblazer/activity/dsl/strategy/railway.rb +0 -23
  55. data/lib/trailblazer/activity/interface.rb +0 -16
  56. data/lib/trailblazer/activity/task_wrap/merge.rb +0 -23
  57. data/lib/trailblazer/activity/task_wrap/trace.rb +0 -44
  58. data/lib/trailblazer/circuit.rb +0 -71
@@ -1,16 +0,0 @@
1
- class Trailblazer::Activity < Module
2
- module Magnetic
3
- module Merge
4
- def merge!(merged)
5
- merged[:record].each do |key, args|
6
- dsl_method, *args = args
7
-
8
- return send( dsl_method, args[0], args[1], &args[2] ) if args[2]
9
- send( dsl_method, args[0], args[1] )
10
- end
11
-
12
- self
13
- end
14
- end
15
- end
16
- end
@@ -1,76 +0,0 @@
1
- module Trailblazer
2
- module Activity::Magnetic
3
- module DSL
4
- # This module only processes additional "wiring" options from the DSL calls
5
- # Output(:success) => End("my.new")
6
- #
7
- # Returns PlusPoles and additional sequence alterations.
8
- module ProcessOptions
9
- module_function
10
-
11
- # Output => target (End/"id"/:color)
12
- # @return [PlusPole]
13
- # @return additional alterations
14
- #
15
- # options:
16
- # { DSL::Output[::Semantic] => target }
17
- #
18
- def call(id, options, plus_poles, &block)
19
- polarization, adds =
20
- options.
21
- collect { |key, task|
22
- # this method call is the only thing that really matters here. # TODO: make this transformation a bit more obvious.
23
- process_tuple(id, key, task, plus_poles, &block)
24
- }.
25
- inject([[],[]]) { |memo, (polarization, adds)| memo[0]<<polarization; memo[1]<<adds; memo }
26
-
27
- return polarization, adds.flatten(1)
28
- end
29
-
30
- def process_tuple(id, output, task, plus_poles, &block)
31
- output = output_for(output, plus_poles) if output.kind_of?(Activity::DSL::OutputSemantic)
32
-
33
- if task.kind_of?(Activity::End)
34
- # raise %{An end event with semantic `#{task.to_h[:semantic]}` has already been added. Please use an ID reference: `=> "End.#{task.to_h[:semantic]}"`} if
35
- new_edge = "#{id}-#{output.signal}"
36
-
37
- [
38
- Polarization.new( output: output, color: new_edge ),
39
- [ [:add, [task.to_h[:semantic], [ [new_edge], task, [] ], group: :end]] ]
40
- ]
41
- # procs come from DSL calls such as `Path() do ... end`.
42
- elsif task.is_a?(Proc)
43
- start_color, activity = task.(block)
44
-
45
- adds = activity.to_h[:adds]
46
-
47
- [
48
- Polarization.new( output: output, color: start_color ),
49
- # TODO: this is a pseudo-"merge" and should be public API at some point.
50
- # TODO: we also need to merge all the other states such as debug.
51
- adds[1..-1] # drop start
52
- ]
53
- elsif task.is_a?(Activity::DSL::Track) # An additional plus polarization. Example: Output => :success
54
- [
55
- Polarization.new( output: output, color: task.color )
56
- ]
57
- else # ID: existing step
58
- new_edge = "#{id}-#{output.signal}-#{task}" # edge from <id> to <target>
59
-
60
- [
61
- Polarization.new( output: output, color: new_edge ),
62
- [[ :magnetic_to, [ task, [new_edge] ] ]], # mark target (`task`) as magnetic to the new edge.
63
- ]
64
- end
65
- end
66
-
67
- # @param semantic DSL::Output::Semantic
68
- def output_for(semantic, plus_poles)
69
- # DISCUSS: review PlusPoles#[]
70
- output, _ = plus_poles.instance_variable_get(:@plus_poles)[semantic.value]
71
- output or raise("Couldn't find existing output for `#{semantic.value.inspect}`.")
72
- end
73
- end # OptionsProcessing
74
- end # DSL
75
- end
76
- end
@@ -1,44 +0,0 @@
1
- module Trailblazer
2
- module Activity::Magnetic
3
- module DSL
4
- # works on a generic Dependencies structure that has no knowledge of magnetism.
5
- class Alterations
6
- def initialize
7
- @groups = Activity::Schema::Dependencies.new
8
- @future_magnetic_to = {} # DISCUSS: future - should it be here?
9
- end
10
-
11
- def add(id, options, **sequence_options)
12
- @groups.add(id, options, **sequence_options)
13
-
14
- # DISCUSS: future - should it be here?
15
- if magnetic_to = @future_magnetic_to.delete(id)
16
- magnetic_to( id, magnetic_to )
17
- end
18
-
19
- self
20
- end
21
-
22
- # make `id` magnetic_to
23
- def magnetic_to(id, magnetic_to)
24
- group, index = @groups.find(id) # this can be a future task!
25
-
26
- unless group # DISCUSS: future - should it be here?
27
- @future_magnetic_to[id] = magnetic_to
28
- return
29
- end
30
-
31
- arr = group[index].configuration.dup
32
-
33
- arr[0] = arr[0] + magnetic_to
34
- group.add(id, arr, replace: id)
35
- end
36
-
37
- # Returns array of tripletts.
38
- def to_a
39
- @groups.to_a
40
- end
41
- end
42
- end # DSL
43
- end
44
- end
@@ -1,85 +0,0 @@
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
- # FIXME: should this be a hash or whatever?
77
- #
78
- # @return Hash All {Output}s mapped to their (guessed) semantic: `{ Output(Right, :success) => :success }`
79
- def self.initial(outputs)
80
- new.merge(Hash[ outputs.collect { |semantic, output| [output, semantic] } ])
81
- end
82
- end
83
- end
84
- end
85
-
@@ -1,23 +0,0 @@
1
- module Trailblazer
2
- module Activity::Magnetic
3
- module DSL
4
- # Every DSL method creates a set of polarizations that are evaluated and decide about a task's
5
- # incoming and outgoing connections.
6
- #
7
- # @note The API of Polarization might be simplified soon.
8
- # @api private
9
- class Polarization
10
- def initialize( output:raise, color:raise )
11
- @output, @color = output, color
12
- end
13
-
14
- def call(magnetic_to, plus_poles, options)
15
- [
16
- magnetic_to,
17
- plus_poles.merge( @output => @color ) # this usually adds a new Output to the task.
18
- ]
19
- end
20
- end # Polarization
21
- end
22
- end
23
- end
@@ -1,11 +0,0 @@
1
- module Trailblazer
2
- class Activity < Module
3
- module DSL
4
- # {:extension API}
5
- # Record each DSL call (like #step) on the activity.
6
- def self.record(activity, *args, original_dsl_args:)
7
- activity[:record, original_dsl_args[1]] = original_dsl_args
8
- end
9
- end
10
- end
11
- end
@@ -1,46 +0,0 @@
1
- module Trailblazer
2
- module Activity::Schema
3
- # Helps organizing the structure of the circuit and allows to define steps that
4
- # might be inserted in a completely different order, but it's experimental.
5
- #
6
- # Translates linear DSL calls that might refer to the same task several times into a linear "drawing instruction"
7
- # that can be consumed by Schema.bla.
8
- #
9
- # This class is experimental.
10
- class Dependencies
11
- def initialize
12
- @groups = {
13
- start: Sequence.new,
14
- main: Sequence.new, # normal steps
15
- end: Sequence.new, # ends
16
- unresolved: Sequence.new, # div
17
- }
18
-
19
- @order = [ :start, :main, :end, :unresolved ]
20
- end
21
-
22
- def add(id, seq_options, group: :main, **sequence_options)
23
- group = @groups[group] or raise "unknown group #{group}, implement me"
24
-
25
- group.add(id, seq_options, **sequence_options) # handles
26
- end
27
-
28
- def to_a
29
- @order.collect{ |name| @groups[name].to_a }.flatten(1)
30
- end
31
-
32
- # @api private
33
- def find(id)
34
- @groups.find do |name, group|
35
- index = group.send( :find_index, id )
36
- return group, index if index
37
- end
38
- end
39
-
40
- # @api private
41
- def self.sequence_keywords
42
- [ :group, :before, :after, :replace, :delete ]
43
- end
44
- end
45
- end
46
- end
@@ -1,46 +0,0 @@
1
- module Trailblazer
2
- module Activity::Schema
3
- # the list of what tasks to add to the graph, for the "drawer"
4
- # produces immutable list of: (node, magnetic_to (incoming colors), outgoing colors)
5
- # via #to_a
6
-
7
- #mutable, for DSL
8
- #
9
- # @api private
10
- class Sequence < ::Array
11
- Element = Struct.new(:id, :configuration)
12
-
13
- # Insert the task into {Sequence} array by respecting options such as `:before`.
14
- # This mutates the object per design.
15
- #
16
- # @param wiring [ [:success, :special_1], A, [ Output, Output ] ]
17
- def add(id, wiring, before:nil, after:nil, replace:nil, delete:nil)
18
- element = Element.new(id, wiring).freeze
19
-
20
- return insert(find_index!(before), element) if before
21
- return insert(find_index!(after)+1, element) if after
22
- return self[find_index!(replace)] = element if replace
23
- return delete_at(find_index!(delete)) if delete
24
-
25
- self << element
26
- end
27
-
28
- def to_a
29
- collect { |element| element.configuration }
30
- end
31
-
32
- private
33
-
34
- def find_index(id)
35
- element = find { |el| el.id == id }
36
- index(element)
37
- end
38
-
39
- def find_index!(id)
40
- find_index(id) or raise IndexError.new(id)
41
- end
42
-
43
- class IndexError < IndexError; end
44
- end
45
- end
46
- end
@@ -1,32 +0,0 @@
1
- class Trailblazer::Activity < Module
2
- module BuildState
3
- # Compute all objects that need to be passed into the new Activity module.
4
- # 1. Build the normalizer (unless passed with :normalizer)
5
- # 2. Build the builder (in State)
6
- # 3. Let State compute all state variables (that implies recompiling the Process)
7
- #
8
- # @return [Builder, Adds, Process, Outputs, remaining options]
9
- # @api private
10
- def self.build_state_for(default_options, options)
11
- options = default_options.merge(options) # TODO: use Variables::Merge() here.
12
- normalizer, options = build_normalizer(options)
13
- builder, adds, circuit, outputs, options = build_state(normalizer, options)
14
- end
15
-
16
- # Builds the normalizer (to process options in DSL calls) unless {:normalizer} is already set.
17
- #
18
- # @api private
19
- def self.build_normalizer(normalizer_class:, normalizer: false, **options)
20
- normalizer, options = normalizer_class.build( options ) unless normalizer
21
-
22
- return normalizer, options
23
- end
24
-
25
- # @api private
26
- def self.build_state(normalizer, builder_class:, builder_options: {}, **options)
27
- builder, adds, circuit, outputs = Magnetic::Builder::State.build(builder_class, normalizer, options.merge(builder_options))
28
-
29
- return builder, adds, circuit, outputs, options
30
- end
31
- end
32
- end
@@ -1,24 +0,0 @@
1
- class Trailblazer::Activity < Module
2
- def self.FastTrack(options={})
3
- FastTrack.new(FastTrack, options)
4
- end
5
-
6
- # Implementation module that can be passed to `Activity[]`.
7
- class FastTrack < Trailblazer::Activity
8
- def self.config
9
- Railway.config.merge(
10
- builder_class: Magnetic::Builder::FastTrack,
11
- extend: [
12
- DSL.def_dsl(:step, Magnetic::Builder::FastTrack, :StepPolarizations),
13
- DSL.def_dsl(:fail, Magnetic::Builder::FastTrack, :FailPolarizations),
14
- DSL.def_dsl(:pass, Magnetic::Builder::FastTrack, :PassPolarizations),
15
- DSL.def_dsl(:_end, Magnetic::Builder::Path, :EndEventPolarizations), # TODO: TEST ME
16
- ],
17
- )
18
- end
19
-
20
- # Signals
21
- FailFast = Class.new(Signal)
22
- PassFast = Class.new(Signal)
23
- end
24
- end
@@ -1,26 +0,0 @@
1
- module Trailblazer
2
- class Activity < Module
3
- def self.Path(options={})
4
- Activity::Path.new(Path, options)
5
- end
6
-
7
- # Implementation module that can be passed to `Activity[]`.
8
- class Path < Activity
9
- # Default variables, called in {Activity::initialize}.
10
- def self.config
11
- {
12
- builder_class: Magnetic::Builder::Path, # we use the Activity-based Normalizer
13
- normalizer_class: Magnetic::Normalizer,
14
- default_outputs: Magnetic::Builder::Path.default_outputs, # binary outputs
15
-
16
- extend: [
17
- # DSL.def_dsl(:task, Magnetic::Builder::Path, :PassPolarizations),
18
- DSL.def_dsl(:_end, Magnetic::Builder::Path, :EndEventPolarizations),
19
- DSL.def_dsl(:task, Magnetic::Builder::Railway, :PassPolarizations),
20
- ],
21
- }
22
- end
23
- end # Path
24
- end
25
- end
26
-
@@ -1,36 +0,0 @@
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
-