trailblazer-activity 0.3.2 → 0.4.o

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 (43) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +4 -3
  3. data/CHANGES.md +4 -0
  4. data/lib/trailblazer/activity.rb +82 -140
  5. data/lib/trailblazer/activity/config.rb +37 -0
  6. data/lib/trailblazer/activity/dsl/add_task.rb +22 -0
  7. data/lib/trailblazer/activity/dsl/helper.rb +49 -0
  8. data/lib/trailblazer/activity/implementation/build_state.rb +31 -0
  9. data/lib/trailblazer/activity/implementation/fast_track.rb +14 -0
  10. data/lib/trailblazer/activity/implementation/interface.rb +16 -0
  11. data/lib/trailblazer/activity/implementation/path.rb +55 -0
  12. data/lib/trailblazer/activity/implementation/railway.rb +18 -0
  13. data/lib/trailblazer/activity/{introspection.rb → introspect.rb} +33 -11
  14. data/lib/trailblazer/activity/magnetic.rb +7 -18
  15. data/lib/trailblazer/activity/magnetic/builder.rb +37 -92
  16. data/lib/trailblazer/activity/magnetic/builder/default_normalizer.rb +26 -0
  17. data/lib/trailblazer/activity/magnetic/builder/fast_track.rb +13 -15
  18. data/lib/trailblazer/activity/magnetic/builder/normalizer.rb +105 -0
  19. data/lib/trailblazer/activity/magnetic/builder/path.rb +14 -15
  20. data/lib/trailblazer/activity/magnetic/builder/railway.rb +8 -11
  21. data/lib/trailblazer/activity/magnetic/dsl.rb +4 -1
  22. data/lib/trailblazer/activity/magnetic/finalizer.rb +1 -1
  23. data/lib/trailblazer/activity/magnetic/merge.rb +18 -0
  24. data/lib/trailblazer/activity/present.rb +1 -1
  25. data/lib/trailblazer/activity/schema/dependencies.rb +6 -1
  26. data/lib/trailblazer/activity/state.rb +58 -0
  27. data/lib/trailblazer/activity/structures.rb +1 -2
  28. data/lib/trailblazer/activity/subprocess.rb +6 -3
  29. data/lib/trailblazer/activity/task_builder.rb +38 -0
  30. data/lib/trailblazer/activity/task_wrap.rb +46 -0
  31. data/lib/trailblazer/{wrap → activity/task_wrap}/call_task.rb +3 -3
  32. data/lib/trailblazer/activity/task_wrap/merge.rb +23 -0
  33. data/lib/trailblazer/{wrap → activity/task_wrap}/runner.rb +14 -16
  34. data/lib/trailblazer/{wrap → activity/task_wrap}/trace.rb +3 -3
  35. data/lib/trailblazer/activity/trace.rb +22 -28
  36. data/lib/trailblazer/activity/version.rb +2 -2
  37. data/lib/trailblazer/circuit.rb +7 -5
  38. data/trailblazer-activity.gemspec +2 -1
  39. metadata +39 -14
  40. data/lib/trailblazer/activity/heritage.rb +0 -30
  41. data/lib/trailblazer/activity/magnetic/builder/block.rb +0 -37
  42. data/lib/trailblazer/activity/process.rb +0 -16
  43. data/lib/trailblazer/activity/wrap.rb +0 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 45961f74078de84b48e1d65403b6924e82fef026
4
- data.tar.gz: 29aab14192b6de4e418ac9668b3aa306c785420f
2
+ SHA256:
3
+ metadata.gz: 7eb2fd05fd42b86db598839e4903e7f81cd44f43f435625a2907c689df522675
4
+ data.tar.gz: f83b35f3c13b44f11f36eec569fbcb008f5681a935ce078316648dd7036a7e88
5
5
  SHA512:
6
- metadata.gz: 0e5ec16c9bbf0c3f7ce34bf2b80d544cc51dd750c21a5f4516413b5ce83121642fa8ad5cf47cd6790168f479a57adcc0252da9c0beafdc82ce0802e1ea213965
7
- data.tar.gz: e38ad33a55650947db2df5aa87b785d78d6c1f92603afcfe26352dfb36f92454a017e5ea08148249afb1524b4fa5464ff1c4f48bc01f0947700619d358f767b6
6
+ metadata.gz: f1b5afb1f62768f177a77dece7954d0251df6f2568373e134aa54aa4535998bba270795ffc200b00bd6b5cb892237452bf0799f492d35cc8ad43fe0e13f83714
7
+ data.tar.gz: 0e6c7a8abb6b7e5db35ac1a154389eed2c6462e6fce1fcd8d502edf4cfd8484037a1c769b096add34a952b74ca1eac4630861d245c4c955d5d8528f343b6d0c7
data/.travis.yml CHANGED
@@ -1,13 +1,14 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
- - 2.0
4
+ # - 2.0
5
5
  - 2.1
6
6
  - 2.2
7
7
  - 2.3.3
8
- - 2.4.0
8
+ - 2.4.1
9
+ - 2.5.0
9
10
  matrix:
10
11
  include:
11
- - rvm: jruby-9.1.13.0
12
+ - rvm: jruby-9.1.15.0
12
13
  env: JRUBY_OPTS="--profile.api"
13
14
  before_install: gem install bundler
data/CHANGES.md CHANGED
@@ -1,3 +1,7 @@
1
+ # 0.4.0
2
+
3
+ * We now use the "Module Subclass" pattern, and activities aren't classes anymore but modules.
4
+
1
5
  # 0.3.2
2
6
 
3
7
  * In the `TaskWrap`, rename `:result_direction` to `:return_signal` and `:result_args` to `:return_args`,
@@ -1,177 +1,119 @@
1
- require "trailblazer/circuit"
1
+ require "trailblazer/activity/version"
2
2
 
3
3
  module Trailblazer
4
- class Activity
5
- module Interface
6
- def decompose # TODO: test me
7
- @process.instance_variable_get(:@circuit).to_fields
8
- end
9
-
10
- def debug # TODO: TEST ME
11
- @debug
12
- end
13
- end
14
-
15
- extend Interface
16
-
17
- require "trailblazer/activity/version"
18
- require "trailblazer/activity/structures"
19
-
20
- require "trailblazer/activity/subprocess"
21
-
22
- require "trailblazer/activity/wrap"
23
- require "trailblazer/wrap/call_task"
24
- require "trailblazer/wrap/trace"
25
- require "trailblazer/wrap/runner"
26
-
27
- require "trailblazer/activity/trace"
28
- require "trailblazer/activity/present"
29
-
4
+ def self.Activity(implementation=Activity::Path, options={})
5
+ Activity.new(implementation, state)
6
+ end
30
7
 
31
- require "trailblazer/activity/magnetic" # the "magnetic" DSL
32
- require "trailblazer/activity/schema/sequence"
8
+ class Activity < Module
9
+ attr_reader :initial_state
33
10
 
34
- require "trailblazer/activity/process"
35
- require "trailblazer/activity/introspection"
11
+ def initialize(implementation, options)
12
+ builder, adds, circuit, outputs, options = BuildState.build_state_for( implementation.config, options)
36
13
 
37
- require "trailblazer/activity/heritage"
14
+ @initial_state = State::Config.build(
15
+ builder: builder,
16
+ options: options,
17
+ adds: adds,
18
+ circuit: circuit,
19
+ outputs: outputs,
20
+ )
38
21
 
39
- def self.call(args, circuit_options={})
40
- @process.( args, circuit_options )
22
+ include *options[:extend] # include the DSL methods.
23
+ include PublicAPI
41
24
  end
42
25
 
43
- #- modelling
44
-
45
- # @private
46
- # DISCUSS: #each instead?
47
- # FIXME: move to Introspection
48
- def self.find(&block)
49
- @process.instance_variable_get(:@circuit).instance_variable_get(:@map).find(&block)
50
- end
51
-
52
- def self.outputs
53
- @outputs
26
+ # Injects the initial configuration into the module defining a new activity.
27
+ def extended(extended)
28
+ super
29
+ extended.instance_variable_set(:@state, initial_state)
54
30
  end
55
31
 
56
- #- DSL part
57
32
 
58
- def self.build(&block)
59
- Class.new(self, &block)
33
+ module Inspect
34
+ def inspect
35
+ "#<Trailblazer::Activity: {#{name || self[:options][:name]}}>"
36
+ end
60
37
  end
61
38
 
62
- private
63
39
 
64
- def self.inherited(subclass)
65
- super
66
- subclass.initialize!(*subclass.config)
67
- heritage.(subclass)
68
- end
69
-
70
- def self.initialize!(builder_class, normalizer)
71
- initialize_activity_dsl!(builder_class, normalizer)
72
- recompile_process!
73
- end
40
+ require "trailblazer/activity/dsl/helper"
41
+ # Helpers such as Path, Output, End to be included into {Activity}.
42
+ module DSLHelper
43
+ extend Forwardable
44
+ def_delegators :@builder, :Path
45
+ def_delegators DSL::Helper, :Output, :End
74
46
 
75
- # builder is stateless, it's up to you to save @adds somewhere.
76
- def self.initialize_activity_dsl!(builder_class, normalizer)
77
- @builder, @adds = builder_class.for( normalizer ) # e.g. Path.for(...) which creates a Builder::Path instance.
78
- @debug = {} # only @adds and @debug are mutable
79
- end
80
-
81
- def self.recompile_process!
82
- @process, @outputs = Recompile.( @adds )
47
+ def Path(*args, &block)
48
+ self[:builder].Path(*args, &block)
49
+ end
83
50
  end
84
51
 
85
- def self.config # FIXME: the normalizer is the same we have in Builder::plan.
86
- return Magnetic::Builder::Path, Magnetic::Builder::DefaultNormalizer.new(plus_poles: Magnetic::Builder::Path.default_plus_poles)
87
- end
52
+ module Accessor
53
+ def []=(*args)
54
+ @state = State::Config.send(:[]=, @state, *args)
55
+ end
88
56
 
89
- # DSL part
90
-
91
- # DISCUSS: make this functions and don't include?
92
- module DSL
93
-
94
- # Create a new method (e.g. Activity::step) that delegates to its builder, recompiles
95
- # the process, etc. Method comes in a module so it can be overridden via modules.
96
- #
97
- # This approach assumes you maintain a @adds and a @debug instance variable. and #heritage
98
- def self.def_dsl!(_name)
99
- Module.new do
100
- define_method(_name) do |*args, &block|
101
- _task(_name, *args, &block) # TODO: similar to Block.
102
- end
103
- end
57
+ def [](*args)
58
+ State::Config[@state, *args]
104
59
  end
60
+ end
105
61
 
106
- private
62
+ # FIXME: still to be decided
63
+ # By including those modules, we create instance methods.
64
+ # Later, this module is `extended` in Path, Railway and FastTrack, and
65
+ # imports the DSL methods as class methods.
66
+ module PublicAPI
67
+ include Accessor
107
68
 
108
- def _task(name, *args, &block)
109
- heritage.record(name, *args, &block)
69
+ require "trailblazer/activity/dsl/add_task"
70
+ include DSL::AddTask
110
71
 
111
- adds, *returned_options = @builder.send(name, *args, &block)
72
+ require "trailblazer/activity/implementation/interface"
73
+ include Activity::Interface # DISCUSS
112
74
 
113
- @adds += adds
114
- @adds.freeze
75
+ include DSLHelper # DISCUSS
115
76
 
116
- recompile_process!
77
+ include Activity::Inspect # DISCUSS
117
78
 
118
- add_introspection!(adds, *returned_options)
79
+ require "trailblazer/activity/magnetic/merge"
80
+ include Magnetic::Merge # Activity#merge!
119
81
 
120
- return adds, returned_options
121
- end
82
+ def call(args, argumenter: [], **circuit_options) # DISCUSS: the argumenter logic might be moved out.
83
+ _, args, circuit_options = argumenter.inject( [self, args, circuit_options] ) { |memo, argumenter| argumenter.(*memo) }
122
84
 
123
- def add_introspection!(adds, task, local_options, *)
124
- @debug[task] = { id: local_options[:id] }.freeze
85
+ self[:circuit].( args, circuit_options.merge(argumenter: argumenter) )
125
86
  end
126
87
  end
88
+ end # Activity
89
+ end
127
90
 
128
- # delegate as much as possible to Builder
129
- # let us process options and e.g. do :id
130
- class << self
131
- extend Forwardable # TODO: test those helpers
132
- def_delegators :@builder, :Path#, :task
133
- end
134
-
135
- extend DSL # _task, :add_introspection
136
- extend DSL.def_dsl!(:task) # define Activity::task.
137
-
138
- extend Heritage::Accessor
91
+ require "trailblazer/circuit"
92
+ require "trailblazer/activity/structures"
93
+ require "trailblazer/activity/config"
139
94
 
95
+ require "trailblazer/activity/implementation/build_state"
96
+ require "trailblazer/activity/implementation/interface"
97
+ require "trailblazer/activity/implementation/path"
98
+ require "trailblazer/activity/implementation/railway"
99
+ require "trailblazer/activity/implementation/fast_track"
140
100
 
141
- # MOVE ME TO ADDS
142
- module Recompile
143
- # Recompile the process and outputs from the {ADDS} instance that collects circuit tasks and connections.
144
- def self.call(adds)
145
- process, end_events = Magnetic::Builder::Finalizer.(adds)
146
- outputs = recompile_outputs(end_events)
101
+ require "trailblazer/activity/task_wrap"
102
+ require "trailblazer/activity/task_wrap/call_task"
103
+ require "trailblazer/activity/task_wrap/trace"
104
+ require "trailblazer/activity/task_wrap/runner"
105
+ require "trailblazer/activity/task_wrap/merge"
147
106
 
148
- return process, outputs
149
- end
107
+ require "trailblazer/activity/trace"
108
+ require "trailblazer/activity/present"
150
109
 
151
- private
110
+ require "trailblazer/activity/introspect"
152
111
 
153
- def self.recompile_outputs(end_events)
154
- ary = end_events.collect do |evt|
155
- [
156
- semantic = evt.instance_variable_get(:@options)[:semantic], # DISCUSS: better API here?
157
- Activity::Output(evt, semantic)
158
- ]
159
- end
160
-
161
- ::Hash[ ary ]
162
- end
163
- end
112
+ # require "trailblazer/activity/heritage"
113
+ require "trailblazer/activity/subprocess"
164
114
 
165
- # TODO: hm
166
- class Railway < Activity
167
- def self.config # FIXME: the normalizer is the same we have in Builder::plan.
168
- return Magnetic::Builder::Railway, Magnetic::Builder::DefaultNormalizer.new(plus_poles: Magnetic::Builder::Railway.default_plus_poles)
169
- end
115
+ require "trailblazer/activity/state"
116
+ require "trailblazer/activity/magnetic" # the "magnetic" DSL
117
+ require "trailblazer/activity/schema/sequence"
170
118
 
171
- extend DSL
172
- extend DSL.def_dsl!(:step)
173
- extend DSL.def_dsl!(:fail)
174
- extend DSL.def_dsl!(:pass)
175
- end
176
- end
177
- end
119
+ require "trailblazer/activity/magnetic/builder/normalizer" # DISCUSS: name and location are odd. This one uses Activity ;)
@@ -0,0 +1,37 @@
1
+ module Trailblazer
2
+ module Activity::State
3
+ # Compile-time
4
+ #
5
+ # DISCUSS: we could replace parts with Hamster::Hash.
6
+ class Config
7
+ def self.build(variables={})
8
+ Hash[ variables.collect { |k,v| [k, v.freeze] } ].freeze
9
+ end
10
+
11
+ def self.[]=(state, *args)
12
+ if args.size == 2
13
+ key, value = *args
14
+
15
+ state = state.merge(key => value)
16
+ else
17
+ directive, key, value = *args
18
+
19
+ state = state.merge( directive => {}.freeze ) unless state.key?(directive)
20
+
21
+ directive_hash = state[directive].merge(key => value)
22
+ state = state.merge( directive => directive_hash.freeze )
23
+ end
24
+
25
+ state
26
+ end
27
+
28
+ def self.[](state, *args)
29
+ directive, key = *args
30
+
31
+ return state[directive] if args.size == 1
32
+ return state[directive][key] if state.key?(directive)
33
+ nil
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,22 @@
1
+ class Trailblazer::Activity < Module
2
+ module DSL
3
+ module AddTask
4
+ def add_task!(name, task, options, &block)
5
+ # The beautiful thing about State.add is it doesn't mutate anything.
6
+ # We're changing state here, on the outside, by overriding the ivars.
7
+ # That in turn means, the only mutated entity is this module.
8
+
9
+ _builder, adds, circuit, outputs, options = State.add( self[:builder], self[:adds], name, task, options, &block ) # this could be an extension itself.
10
+
11
+ self[:adds] = adds
12
+ self[:circuit] = circuit
13
+ self[:outputs] = outputs
14
+
15
+ task, local_options = options
16
+
17
+ # {Extension API} call all extensions.
18
+ local_options[:extension].collect { |ext| ext.(self, *options) } if local_options[:extension]
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,49 @@
1
+ module Trailblazer
2
+ module Activity::DSL
3
+ # Create a new method (e.g. Activity::step) that delegates to its builder, recompiles
4
+ # the circuit, etc. Method comes in a module so it can be overridden via modules.
5
+ #
6
+ # This approach assumes you maintain a {#add_task!} method.
7
+ def self.def_dsl(_name)
8
+ Module.new do
9
+ define_method(_name) do |task, options={}, &block|
10
+ builder, adds, circuit, outputs, options = add_task!(_name, task, options, &block) # TODO: similar to Block.
11
+ end
12
+ end
13
+ end
14
+
15
+ # Shortcut functions for the DSL. These have no state.
16
+ module Helper
17
+ module_function
18
+
19
+ # Output( Left, :failure )
20
+ # Output( :failure ) #=> Output::Semantic
21
+ def Output(signal, semantic=nil)
22
+ return Activity::Magnetic::DSL::Output::Semantic.new(signal) if semantic.nil?
23
+
24
+ Activity.Output(signal, semantic)
25
+ end
26
+
27
+ def End(name, semantic)
28
+ Activity.End(name, semantic)
29
+ end
30
+
31
+ def Path(normalizer, track_color: "track_#{rand}", end_semantic: :success, **options)
32
+ options = options.merge(track_color: track_color, end_semantic: end_semantic)
33
+
34
+ # Build an anonymous class which will be where the block is evaluated in.
35
+ # We use the same normalizer here, so DSL calls in the inner block have the same behavior.
36
+ path = Module.new do
37
+ extend Activity::Path( options.merge( normalizer: normalizer ) )
38
+ end
39
+
40
+ # this block is called in DSL::ProcessTuples. This could be improved somehow.
41
+ ->(block) {
42
+ path.instance_exec(&block)
43
+
44
+ [ track_color, path ]
45
+ }
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,31 @@
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
+ def self.build_state(normalizer, builder_class:, builder_options: {}, **options)
26
+ builder, adds, circuit, outputs = State.build(builder_class, normalizer, options.merge(builder_options))
27
+
28
+ return builder, adds, circuit, outputs, options
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,14 @@
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
+ )
12
+ end
13
+ end
14
+ end