trailblazer-activity 0.9.1 → 0.9.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +12 -0
- data/lib/trailblazer/activity.rb +0 -4
- data/lib/trailblazer/activity/testing.rb +75 -0
- data/lib/trailblazer/activity/version.rb +1 -1
- metadata +3 -6
- data/lib/trailblazer/activity/introspect.rb +0 -72
- data/lib/trailblazer/activity/present.rb +0 -63
- data/lib/trailblazer/activity/trace.rb +0 -144
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0b971b7f8960520b05bcc99a2fe0561056d9ec244cf9faeb072e131604e0bc12
|
4
|
+
data.tar.gz: ec6e1d2c4b2de4d1edfce435c08029a061df61b1b770ad174c005733238269cb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5de05a662519033f02c6e58595d502e80970b08abe7bd87caa7ff23c6acae6490498453bcf8584b8ea6dcba14ef6f00298b1aeca75c5405f8e281e4d206e44e9
|
7
|
+
data.tar.gz: 35c9f6d275c0da422e0597529424f005af4e44a344c63c0ca8595d87a44ad8c474be21c5e9c985d1f1a01b2d1ff0b2020da06edcc29e9871af9c174c1766d7cb
|
data/CHANGES.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
# 0.9.4
|
2
|
+
|
3
|
+
Move some test helpers to `Activity::Testing` to export them to other gems
|
4
|
+
|
5
|
+
# 0.9.3
|
6
|
+
|
7
|
+
Remove introspection modules, it'll also be part of the `Dev` tools now.
|
8
|
+
|
9
|
+
# 0.9.2
|
10
|
+
|
11
|
+
Remove tracing modules, it'll be part of the `Dev` tools now.
|
12
|
+
|
1
13
|
# 0.9.1
|
2
14
|
|
3
15
|
Use `context-0.9.1`.
|
data/lib/trailblazer/activity.rb
CHANGED
@@ -49,10 +49,6 @@ require "trailblazer/activity/task_wrap/runner"
|
|
49
49
|
require "trailblazer/activity/task_wrap/variable_mapping"
|
50
50
|
require "trailblazer/activity/task_wrap/inject"
|
51
51
|
|
52
|
-
require "trailblazer/activity/trace"
|
53
|
-
require "trailblazer/activity/present"
|
54
|
-
|
55
|
-
require "trailblazer/activity/introspect"
|
56
52
|
require "trailblazer/option"
|
57
53
|
require "trailblazer/context"
|
58
54
|
require "trailblazer/activity/task_builder"
|
@@ -47,10 +47,85 @@ module Trailblazer
|
|
47
47
|
end
|
48
48
|
|
49
49
|
module Assertions
|
50
|
+
Activity = Trailblazer::Activity
|
51
|
+
Inter = Trailblazer::Activity::Schema::Intermediate
|
52
|
+
Schema = Trailblazer::Activity::Schema
|
53
|
+
TaskWrap = Trailblazer::Activity::TaskWrap
|
54
|
+
|
55
|
+
module Implementing
|
56
|
+
extend Activity::Testing.def_tasks(:a, :b, :c, :d, :f, :g)
|
57
|
+
|
58
|
+
Start = Activity::Start.new(semantic: :default)
|
59
|
+
Failure = Activity::End(:failure)
|
60
|
+
Success = Activity::End(:success)
|
61
|
+
end
|
62
|
+
|
50
63
|
def Cct(activity)
|
51
64
|
cct = Trailblazer::Developer::Render::Circuit.(activity)
|
52
65
|
end
|
53
66
|
|
67
|
+
# TODO: Remove this once all it's references are removed
|
68
|
+
def implementing
|
69
|
+
Implementing
|
70
|
+
end
|
71
|
+
|
72
|
+
def flat_activity
|
73
|
+
return @_flat_activity if defined?(@_flat_activity)
|
74
|
+
|
75
|
+
intermediate = Inter.new(
|
76
|
+
{
|
77
|
+
Inter::TaskRef("Start.default") => [Inter::Out(:success, :B)],
|
78
|
+
Inter::TaskRef(:B, additional: true) => [Inter::Out(:success, :C)],
|
79
|
+
Inter::TaskRef(:C) => [Inter::Out(:success, "End.success")],
|
80
|
+
Inter::TaskRef("End.success", stop_event: true) => [Inter::Out(:success, nil)]
|
81
|
+
},
|
82
|
+
["End.success"],
|
83
|
+
["Start.default"], # start
|
84
|
+
)
|
85
|
+
|
86
|
+
implementation = {
|
87
|
+
"Start.default" => Schema::Implementation::Task(st = Implementing::Start, [Activity::Output(Activity::Right, :success)], []),
|
88
|
+
:B => Schema::Implementation::Task(b = Implementing.method(:b), [Activity::Output(Activity::Right, :success)], []),
|
89
|
+
:C => Schema::Implementation::Task(c = Implementing.method(:c), [Activity::Output(Activity::Right, :success)], []),
|
90
|
+
"End.success" => Schema::Implementation::Task(_es = Implementing::Success, [Activity::Output(Implementing::Success, :success)], []), # DISCUSS: End has one Output, signal is itself?
|
91
|
+
}
|
92
|
+
|
93
|
+
schema = Inter.(intermediate, implementation)
|
94
|
+
|
95
|
+
@_flat_activity = Activity.new(schema)
|
96
|
+
end
|
97
|
+
|
98
|
+
def nested_activity
|
99
|
+
return @_nested_activity if defined?(@_nested_activity)
|
100
|
+
|
101
|
+
intermediate = Inter.new(
|
102
|
+
{
|
103
|
+
Inter::TaskRef("Start.default") => [Inter::Out(:success, :B)],
|
104
|
+
Inter::TaskRef(:B, more: true) => [Inter::Out(:success, :D)],
|
105
|
+
Inter::TaskRef(:D) => [Inter::Out(:success, :E)],
|
106
|
+
Inter::TaskRef(:E) => [Inter::Out(:success, "End.success")],
|
107
|
+
Inter::TaskRef("End.success", stop_event: true) => [Inter::Out(:success, nil)]
|
108
|
+
},
|
109
|
+
["End.success"],
|
110
|
+
["Start.default"] # start
|
111
|
+
)
|
112
|
+
|
113
|
+
implementation = {
|
114
|
+
"Start.default" => Schema::Implementation::Task(st = Implementing::Start, [Activity::Output(Activity::Right, :success)], []),
|
115
|
+
:B => Schema::Implementation::Task(b = Implementing.method(:b), [Activity::Output(Activity::Right, :success)], []),
|
116
|
+
:D => Schema::Implementation::Task(c = bc, [Activity::Output(Implementing::Success, :success)], []),
|
117
|
+
:E => Schema::Implementation::Task(e = Implementing.method(:f), [Activity::Output(Activity::Right, :success)], []),
|
118
|
+
"End.success" => Schema::Implementation::Task(_es = Implementing::Success, [Activity::Output(Implementing::Success, :success)], []), # DISCUSS: End has one Output, signal is itself?
|
119
|
+
}
|
120
|
+
|
121
|
+
schema = Inter.(intermediate, implementation)
|
122
|
+
|
123
|
+
@_nested_activity = Activity.new(schema)
|
124
|
+
end
|
125
|
+
|
126
|
+
alias_method :bc, :flat_activity
|
127
|
+
alias_method :bde, :nested_activity
|
128
|
+
|
54
129
|
# Tests {:circuit} and {:outputs} fields so far.
|
55
130
|
def assert_process_for(process, *args)
|
56
131
|
semantics, circuit = args[0..-2], args[-1]
|
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.9.
|
4
|
+
version: 0.9.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Sutterer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-09-
|
11
|
+
date: 2019-09-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: trailblazer-context
|
@@ -108,8 +108,6 @@ files:
|
|
108
108
|
- lib/trailblazer/activity.rb
|
109
109
|
- lib/trailblazer/activity/circuit.rb
|
110
110
|
- lib/trailblazer/activity/config.rb
|
111
|
-
- lib/trailblazer/activity/introspect.rb
|
112
|
-
- lib/trailblazer/activity/present.rb
|
113
111
|
- lib/trailblazer/activity/schema.rb
|
114
112
|
- lib/trailblazer/activity/schema/implementation.rb
|
115
113
|
- lib/trailblazer/activity/schema/intermediate.rb
|
@@ -122,7 +120,6 @@ files:
|
|
122
120
|
- lib/trailblazer/activity/task_wrap/runner.rb
|
123
121
|
- lib/trailblazer/activity/task_wrap/variable_mapping.rb
|
124
122
|
- lib/trailblazer/activity/testing.rb
|
125
|
-
- lib/trailblazer/activity/trace.rb
|
126
123
|
- lib/trailblazer/activity/version.rb
|
127
124
|
- trailblazer-activity.gemspec
|
128
125
|
homepage: http://trailblazer.to
|
@@ -145,7 +142,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
145
142
|
version: '0'
|
146
143
|
requirements: []
|
147
144
|
rubyforge_project:
|
148
|
-
rubygems_version: 2.7.
|
145
|
+
rubygems_version: 2.7.3
|
149
146
|
signing_key:
|
150
147
|
specification_version: 4
|
151
148
|
summary: Runtime code for Trailblazer activities.
|
@@ -1,72 +0,0 @@
|
|
1
|
-
module Trailblazer
|
2
|
-
class Activity
|
3
|
-
# The Introspect API provides inflections for `Activity` instances.
|
4
|
-
# It abstracts internals about circuits and provides a convenient API to third-parties such as
|
5
|
-
# tracing, rendering an activity, or finding particular tasks.
|
6
|
-
module Introspect
|
7
|
-
def self.Graph(*args)
|
8
|
-
Graph.new(*args)
|
9
|
-
end
|
10
|
-
|
11
|
-
# TODO: order of step/fail/pass in Node would be cool to have
|
12
|
-
|
13
|
-
# @private This API is still under construction.
|
14
|
-
class Graph
|
15
|
-
def initialize(activity)
|
16
|
-
@activity = activity
|
17
|
-
@schema = activity.to_h or raise
|
18
|
-
@circuit = @schema[:circuit]
|
19
|
-
@map = @circuit.to_h[:map]
|
20
|
-
@configs = @schema[:nodes]
|
21
|
-
end
|
22
|
-
|
23
|
-
def find(id=nil, &block)
|
24
|
-
return find_by_id(id) unless block_given?
|
25
|
-
find_with_block(&block)
|
26
|
-
end
|
27
|
-
|
28
|
-
def collect(strategy: :circuit, &block)
|
29
|
-
@map.keys.each_with_index.collect { |task, i| yield find_with_block { |node| node.task==task }, i }
|
30
|
-
end
|
31
|
-
|
32
|
-
def stop_events
|
33
|
-
@circuit.to_h[:end_events]
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def find_by_id(id)
|
39
|
-
node = @configs.find { |node| node.id == id } or return
|
40
|
-
node_for(node)
|
41
|
-
end
|
42
|
-
|
43
|
-
def find_with_block(&block)
|
44
|
-
existing = @configs.find { |node| yield Node(node.task, node.id, node.outputs, node.data) } or return
|
45
|
-
|
46
|
-
node_for(existing)
|
47
|
-
end
|
48
|
-
|
49
|
-
def node_for(node_attributes)
|
50
|
-
Node(node_attributes.task, node_attributes.id, node_attributes.outputs, outgoings_for(node_attributes), node_attributes.data)
|
51
|
-
end
|
52
|
-
|
53
|
-
def Node(*args)
|
54
|
-
Node.new(*args).freeze
|
55
|
-
end
|
56
|
-
|
57
|
-
Node = Struct.new(:task, :id, :outputs, :outgoings, :data)
|
58
|
-
Outgoing = Struct.new(:output, :task)
|
59
|
-
|
60
|
-
def outgoings_for(node)
|
61
|
-
outputs = node.outputs
|
62
|
-
connections = @map[node.task]
|
63
|
-
|
64
|
-
connections.collect do |signal, target|
|
65
|
-
output = outputs.find { |out| out.signal == signal }
|
66
|
-
Outgoing.new(output, target)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end #Introspect
|
71
|
-
end
|
72
|
-
end
|
@@ -1,63 +0,0 @@
|
|
1
|
-
module Trailblazer
|
2
|
-
class Activity
|
3
|
-
# Task < Array
|
4
|
-
# [ input, ..., output ]
|
5
|
-
|
6
|
-
module Trace
|
7
|
-
# TODO: make this simpler.
|
8
|
-
module Present
|
9
|
-
module_function
|
10
|
-
|
11
|
-
INDENTATION = " |".freeze
|
12
|
-
STEP_PREFIX = "-- ".freeze
|
13
|
-
|
14
|
-
def default_renderer(task_node:, **)
|
15
|
-
[ task_node[:level], %{#{task_node[:name]}} ]
|
16
|
-
end
|
17
|
-
|
18
|
-
def call(stack, level: 1, tree: [], renderer: method(:default_renderer), **options)
|
19
|
-
tree(stack.to_a, level, tree: tree, renderer: renderer, **options)
|
20
|
-
end
|
21
|
-
|
22
|
-
def tree(stack, level, tree:, renderer:, **options)
|
23
|
-
tree_for(stack, level, options.merge(tree: tree))
|
24
|
-
|
25
|
-
nodes = tree.each_with_index.map do |task_node, position|
|
26
|
-
renderer.(task_node: task_node, position: position, tree: tree)
|
27
|
-
end
|
28
|
-
|
29
|
-
render_tree_for(nodes)
|
30
|
-
end
|
31
|
-
|
32
|
-
def render_tree_for(nodes)
|
33
|
-
nodes.map { |level, node|
|
34
|
-
indentation = INDENTATION * (level -1)
|
35
|
-
indentation = indentation[0...-1] + "`" if level == 1 || /End./.match(node) # start or end step
|
36
|
-
indentation + STEP_PREFIX + node
|
37
|
-
}.join("\n")
|
38
|
-
end
|
39
|
-
|
40
|
-
def tree_for(stack, level, tree:, **options)
|
41
|
-
stack.each do |lvl| # always a Stack::Task[input, ..., output]
|
42
|
-
input, output, nested = Trace::Level.input_output_nested_for_level(lvl)
|
43
|
-
|
44
|
-
task = input.task
|
45
|
-
|
46
|
-
graph = Introspect::Graph(input.activity)
|
47
|
-
|
48
|
-
name = (node = graph.find { |node| node[:task] == task }) ? node[:id] : task
|
49
|
-
name ||= task # FIXME: bullshit
|
50
|
-
|
51
|
-
tree << { level: level, input: input, output: output, name: name, **options }
|
52
|
-
|
53
|
-
if nested.any? # nesting
|
54
|
-
tree_for(nested, level + 1, options.merge(tree: tree))
|
55
|
-
end
|
56
|
-
|
57
|
-
tree
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
@@ -1,144 +0,0 @@
|
|
1
|
-
module Trailblazer
|
2
|
-
class Activity
|
3
|
-
module Trace
|
4
|
-
class << self
|
5
|
-
# Public entry point to activate tracing when running {activity}.
|
6
|
-
def call(activity, (ctx, flow_options), circuit_options={})
|
7
|
-
activity, (ctx, flow_options), circuit_options = Trace.arguments_for_call( activity, [ctx, flow_options], circuit_options ) # only run once for the entire circuit!
|
8
|
-
|
9
|
-
signal, (ctx, flow_options) = Activity::TaskWrap.invoke(activity, [ctx, flow_options], circuit_options)
|
10
|
-
|
11
|
-
return flow_options[:stack], signal, [ctx, flow_options]
|
12
|
-
end
|
13
|
-
|
14
|
-
alias_method :invoke, :call
|
15
|
-
|
16
|
-
def arguments_for_call(activity, (options, flow_options), **circuit_options)
|
17
|
-
tracing_flow_options = {
|
18
|
-
stack: Trace::Stack.new,
|
19
|
-
}
|
20
|
-
|
21
|
-
tracing_circuit_options = {
|
22
|
-
wrap_runtime: ::Hash.new(Trace.merge_plan), # DISCUSS: this overrides existing {:wrap_runtime}.
|
23
|
-
}
|
24
|
-
|
25
|
-
return activity, [ options, tracing_flow_options.merge(flow_options) ], circuit_options.merge(tracing_circuit_options)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
module_function
|
30
|
-
# Insertions for the trace tasks that capture the arguments just before calling the task,
|
31
|
-
# and before the TaskWrap is finished.
|
32
|
-
#
|
33
|
-
# @private
|
34
|
-
def merge_plan
|
35
|
-
TaskWrap::Pipeline::Merge.new(
|
36
|
-
[TaskWrap::Pipeline.method(:insert_before), "task_wrap.call_task", ["task_wrap.capture_args", Trace.method(:capture_args)]],
|
37
|
-
[TaskWrap::Pipeline.method(:append), nil, ["task_wrap.capture_return", Trace.method(:capture_return)]],
|
38
|
-
)
|
39
|
-
end
|
40
|
-
|
41
|
-
# taskWrap step to capture incoming arguments of a step.
|
42
|
-
def capture_args(wrap_config, original_args)
|
43
|
-
original_args = capture_for(wrap_config[:task], *original_args)
|
44
|
-
|
45
|
-
return wrap_config, original_args
|
46
|
-
end
|
47
|
-
|
48
|
-
# taskWrap step to capture outgoing arguments from a step.
|
49
|
-
def capture_return(wrap_config, original_args)
|
50
|
-
(original_options, original_flow_options, _) = original_args[0]
|
51
|
-
|
52
|
-
original_flow_options[:stack] << Entity::Output.new(
|
53
|
-
wrap_config[:task], {}, wrap_config[:return_signal]
|
54
|
-
).freeze
|
55
|
-
|
56
|
-
original_flow_options[:stack].unindent!
|
57
|
-
|
58
|
-
|
59
|
-
return wrap_config, original_args
|
60
|
-
end
|
61
|
-
|
62
|
-
# It's important to understand that {flow[:stack]} is mutated by design. This is needed so
|
63
|
-
# in case of exceptions we still have a "global" trace - unfortunately Ruby doesn't allow
|
64
|
-
# us a better way.
|
65
|
-
def capture_for(task, (ctx, flow), activity:, **circuit_options)
|
66
|
-
flow[:stack].indent!
|
67
|
-
|
68
|
-
flow[:stack] << Entity::Input.new(
|
69
|
-
task, activity, [ctx, ctx.inspect]
|
70
|
-
).freeze
|
71
|
-
|
72
|
-
return [ctx, flow], circuit_options.merge(activity: activity)
|
73
|
-
end
|
74
|
-
|
75
|
-
# Structures used in {capture_args} and {capture_return}.
|
76
|
-
# These get pushed onto one {Level} in a {Stack}.
|
77
|
-
#
|
78
|
-
# Level[
|
79
|
-
# Level[ ==> this is a scalar task
|
80
|
-
# Entity::Input
|
81
|
-
# Entity::Output
|
82
|
-
# ]
|
83
|
-
# Level[ ==> nested task
|
84
|
-
# Entity::Input
|
85
|
-
# Level[
|
86
|
-
# Entity::Input
|
87
|
-
# Entity::Output
|
88
|
-
# ]
|
89
|
-
# Entity::Output
|
90
|
-
# ]
|
91
|
-
# ]
|
92
|
-
Entity = Struct.new(:task, :activity, :data)
|
93
|
-
Entity::Input = Class.new(Entity)
|
94
|
-
Entity::Output = Class.new(Entity)
|
95
|
-
|
96
|
-
class Level < Array
|
97
|
-
def inspect
|
98
|
-
%{<Level>#{super}}
|
99
|
-
end
|
100
|
-
|
101
|
-
# @param level {Trace::Level}
|
102
|
-
def self.input_output_nested_for_level(level)
|
103
|
-
input = level[0]
|
104
|
-
output = level[-1]
|
105
|
-
|
106
|
-
output, nested = output.is_a?(Entity::Output) ? [output, level-[input, output]] : [nil, level[1..-1]]
|
107
|
-
|
108
|
-
return input, output, nested
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
# Mutable/stateful per design. We want a (global) stack!
|
113
|
-
class Stack
|
114
|
-
def initialize
|
115
|
-
@nested = Level.new
|
116
|
-
@stack = [ @nested ]
|
117
|
-
end
|
118
|
-
|
119
|
-
def indent!
|
120
|
-
current << indented = Level.new
|
121
|
-
@stack << indented
|
122
|
-
end
|
123
|
-
|
124
|
-
def unindent!
|
125
|
-
@stack.pop
|
126
|
-
end
|
127
|
-
|
128
|
-
def <<(args)
|
129
|
-
current << args
|
130
|
-
end
|
131
|
-
|
132
|
-
def to_a
|
133
|
-
@nested
|
134
|
-
end
|
135
|
-
|
136
|
-
private
|
137
|
-
|
138
|
-
def current
|
139
|
-
@stack.last
|
140
|
-
end
|
141
|
-
end # Stack
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|