trailblazer-circuit 0.0.4 → 0.0.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c9e50c60fbd29ee44bc11f122198acec25c02122
4
- data.tar.gz: de1fb71290d6c4a817827bfad946cf739a1d4291
3
+ metadata.gz: d3c9b6666028fb2423dace64b0d84dfd67427e3a
4
+ data.tar.gz: a2ec4fb343197e3c512a0a0bb1c1a924ecdbee57
5
5
  SHA512:
6
- metadata.gz: c8b5ea44e5ca1a618da4c4b4c5130d27700ada1766c621e4753e4d58765995f6799490e3b842f89183ec1ea860704e0c3d55549270cc1a539fab93b5f503269c
7
- data.tar.gz: 0cf6a6dd1cc39496a236eb2d816e360efca4f60d263a0d591a8f799890bc5e29bd3a8a0ccdcf9b89aa04b11071b40cf7aa0b196e6a7d41f2bf1273df2c646747
6
+ metadata.gz: 72059d24e47902a25d385fd8103907bec6bcdccfbf1bccc443779c2b9d9390bd37c9cced154089aff1741f8974d586350e615ee98a422e32bd89957dc2974cf6
7
+ data.tar.gz: 5a9312bd96dafe6e8675a17c0b8f6c6f32504a15437f48ade8f2131f8c0178ba458456f3102b03d62e1beab93bc08c56c7e7abafdd6c30ab4707e0fcf5bb91c8
data/CHANGES.md CHANGED
@@ -1,3 +1,7 @@
1
+ # 0.0.5
2
+
3
+ * The `Wrapped::Runner` now applies `Alterations` to each task's `Circuit`. This means you can inject `:task_alterations` into `Circuit#call`, which will then be merged into the task's original circuit, and then run. While this might sound like crazy talk, this allows any kind of external injection (tracing, input/output contracts, step dependency injections, ...) for specific or all tasks of any circuit.
4
+
1
5
  # 0.0.4
2
6
 
3
7
  * Simpler tracing with `Stack`.
@@ -7,19 +7,12 @@ module Trailblazer
7
7
  # puts Trailblazer::Circuit::Present.tree(stack) # renders the trail.
8
8
  module Trace
9
9
  def self.call(activity, direction, options, flow_options={})
10
- # activity_wrap is the circuit/pipeline that wraps each step and implements tracing (and more, like input/output contracts, etc!).
11
- activity_wrap = Activity::Before( Activity::Wrapped::Activity, Activity::Wrapped::Call, Trace.method(:capture_args), direction: Right )
12
- activity_wrap = Activity::Before( activity_wrap, Activity::Wrapped::Activity[:End], Trace.method(:capture_return), direction: Right )
13
-
14
- step_runners = {
15
- nil => activity_wrap, # call all steps with tracing.
16
- }
17
-
18
10
  tracing_flow_options = {
19
- runner: Activity::Wrapped::Runner,
20
- stack: Circuit::Trace::Stack.new,
21
- step_runners: step_runners,
22
- debug: activity.circuit.instance_variable_get(:@name)
11
+ runner: Activity::Wrapped::Runner,
12
+ stack: Trace::Stack.new,
13
+ wrap_alterations: Activity::Wrapped::Alterations.new(Trace.Alterations),
14
+ task_wraps: Activity::Wrapped::Wraps.new(Activity::Wrapped::Activity),
15
+ debug: {}, # TODO: set that in Activity::call?
23
16
  }
24
17
 
25
18
  direction, options, flow_options = activity.( direction, options, tracing_flow_options.merge(flow_options) )
@@ -27,16 +20,26 @@ module Trailblazer
27
20
  return flow_options[:stack].to_a, direction, options, flow_options
28
21
  end
29
22
 
23
+ # TODO: test alterations with any wrap_circuit.
24
+
25
+ # Default tracing tasks to be plugged into the wrap circuit.
26
+ def self.Alterations
27
+ [
28
+ ->(wrap_circuit) { Activity::Before( wrap_circuit, Activity::Wrapped::Call, Trace.method(:capture_args), direction: Right ) },
29
+ ->(wrap_circuit) { Activity::Before( wrap_circuit, wrap_circuit[:End], Trace.method(:capture_return), direction: Right ) },
30
+ ]
31
+ end
32
+
30
33
  def self.capture_args(direction, options, flow_options, wrap_config, original_flow_options)
31
34
  original_flow_options[:stack].indent!
32
35
 
33
- original_flow_options[:stack] << [ wrap_config[:step], :args, nil, options.dup, original_flow_options[:debug] ]
36
+ original_flow_options[:stack] << [ wrap_config[:task], :args, nil, options.dup, original_flow_options[:debug] ]
34
37
 
35
38
  [ direction, options, flow_options, wrap_config, original_flow_options ]
36
39
  end
37
40
 
38
41
  def self.capture_return(direction, options, flow_options, wrap_config, original_flow_options)
39
- original_flow_options[:stack] << [ wrap_config[:step], :return, flow_options[:result_direction], options.dup ]
42
+ original_flow_options[:stack] << [ wrap_config[:task], :return, flow_options[:result_direction], options.dup ]
40
43
 
41
44
  original_flow_options[:stack].unindent!
42
45
 
@@ -1,5 +1,5 @@
1
1
  module Trailblazer
2
2
  class Circuit
3
- VERSION = "0.0.4"
3
+ VERSION = "0.0.5"
4
4
  end
5
5
  end
@@ -1,9 +1,52 @@
1
1
  class Trailblazer::Circuit
2
+ # Lingo: task_wrap
2
3
  module Activity::Wrapped
3
- # Input = ->(direction, options, flow_options) { [direction, options, flow_options] }
4
+ # The runner is passed into Circuit#call( runner: Runner ) and is called for every task in the circuit.
5
+ # Its primary job is to actually `call` the task.
6
+ #
7
+ # Here, we extend this, and wrap the task `call` into its own pipeline, so we can add external behavior per task.
8
+ class Runner
9
+ # private flow_options[ :task_wraps ] # DISCUSS: move to separate arg?
10
+ # @api private
11
+ def self.call(task, direction, options, task_wraps:raise, wrap_alterations:{}, **flow_options)
12
+ # TODO: test this decider!
13
+ task_wrap = task_wraps[task] || raise("test me!")
14
+ task_wrap = wrap_alterations.(task, task_wrap)
15
+
16
+ wrap_config = { task: task }
17
+
18
+ # Call the task_wrap circuit:
19
+ # |-- Start
20
+ # |-- Trace.capture_args [optional]
21
+ # |-- Call (call actual task)
22
+ # |-- Trace.capture_return [optional]
23
+ # |-- End
24
+ # Pass empty flow_options to the task_wrap, so it doesn't infinite-loop.
25
+ task_wrap.( task_wrap[:Start], options, {}, wrap_config, flow_options.merge( task_wraps: task_wraps, wrap_alterations: wrap_alterations) )
26
+ end
27
+ end # Runner
28
+
29
+ class Wraps
30
+ def initialize(default, hash={})
31
+ @default, @hash = default, hash
32
+ end
33
+
34
+ def [](task)
35
+ @hash.fetch(task) { @default }
36
+ end
37
+ end
38
+
39
+ class Alterations < Wraps
40
+ # Find alterations for `task` and apply them to `task_wrap`.
41
+ # This usually means that tracing steps/tasks are added, input/output contracts added, etc.
42
+ def call(task, task_wrap)
43
+ self[task].
44
+ inject(task_wrap) { |circuit, alteration| alteration.(circuit) }
45
+ end
46
+ end
4
47
 
5
48
  def self.call_activity(direction, options, flow_options, wrap_config, original_flow_options)
6
- task = wrap_config[:step]
49
+ task = wrap_config[:task]
7
50
 
8
51
  # Call the actual task we're wrapping here.
9
52
  wrap_config[:result_direction], options, flow_options = task.( direction, options, original_flow_options )
@@ -13,46 +56,17 @@ class Trailblazer::Circuit
13
56
 
14
57
  Call = method(:call_activity)
15
58
 
16
- # Output = ->(direction, options, flow_options) { [direction, options, flow_options] }
17
-
18
59
  class End < Trailblazer::Circuit::End
19
60
  def call(direction, options, flow_options, wrap_config, *args)
20
- [ wrap_config[:result_direction], options, flow_options, wrap_config, *args ]
61
+ [ wrap_config[:result_direction], options, flow_options ] # note how we don't return the appended internal args.
21
62
  end
22
63
  end
23
64
 
24
65
  Activity = Trailblazer::Circuit::Activity({ id: "task.wrap" }, end: { default: End.new(:default) }) do |act|
25
66
  {
26
- act[:Start] => { Right => Call }, # options from outside
27
- # Input => { Circuit::Right => Trace::CaptureArgs },
28
- # MyInject => { Circuit::Right => Trace::CaptureArgs },
29
- # Trace::CaptureArgs => { Circuit::Right => Call },
30
- Call => { Right => act[:End] },
31
- # Trace::CaptureReturn => { Circuit::Right => Output },
32
- # Output => { Circuit::Right => act[:End] }
67
+ act[:Start] => { Right => Call }, # options from outside
68
+ Call => { Right => act[:End] },
33
69
  }
34
- end
35
-
36
- # Find the respective wrap per task, and run it.
37
- class Runner
38
- # private flow_options[ :step_runners ]
39
- def self.call(task, direction, options, flow_options)
40
- # TODO: test this decider!
41
- task_wrap = flow_options[:step_runners][task] || flow_options[:step_runners][nil] # DISCUSS: default could be more explicit@
42
-
43
- # we can't pass :runner in here since the Step::Pipeline would call itself again, then.
44
- # However, we need the runner in nested activities.
45
- wrap_config = { step: task }
46
-
47
- # Call the task_wrap circuit:
48
- # |-- Start
49
- # |-- Trace.capture_args [optional]
50
- # |-- Call (call actual task)
51
- # |-- Trace.capture_return [optional]
52
- # |-- End
53
- # Pass empty flow_options to the task_wrap, so it doesn't infinite-loop.
54
- task_wrap.( task_wrap[:Start], options, {}, wrap_config, flow_options ) # all tasks in Wrap have to implement this signature.
55
- end
56
- end # Runner
70
+ end # Activity
57
71
  end
58
72
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trailblazer-circuit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Sutterer
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-06-06 00:00:00.000000000 Z
11
+ date: 2017-06-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler