trailblazer-activity 0.9.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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