trailblazer-developer 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4457d9f0cca19b8f72a8e492f8d155c5d8a3459015201d03548a71b26911f0b2
4
- data.tar.gz: f6035eaca82336afb3d836f40c96910b37298e2c5eee8b90fac93a2d5c563b5f
3
+ metadata.gz: 435373419cdb7bb8f3c3b923585cdd83152774c90cb38b0685cf8ac4bdcc417d
4
+ data.tar.gz: 9f0a93bf955441a20d0f91f538fd3ad563cfda5a3f45b582dfa4edfd0aa8876d
5
5
  SHA512:
6
- metadata.gz: d7c7243f9b266f750a47046e5fce4ad73c08b8e44dcf6ea5bf7b40f008565130bec440ab1c372dcfc312436c7b5ac44b9113a3411677b87954aa4d232696d804
7
- data.tar.gz: ebcd6ebbf1b448a306566b07c1042324eac3291b077cafc62c389cf78533034f187fd467a33e2142ac89d3a7d9b954c873dc31915d1278c71b4ffb7b7921d44e
6
+ metadata.gz: 983662dc11836f0e42050145b5766c2eaa19d6c1240eb6cfe647c3fe6250a38d32cea7392dfc1ebef56c88ee83f9dee95764dfda7fb8c81703dd30eb84486b4b
7
+ data.tar.gz: 7591b6a2004491cf86fbe042009e870aafb9f23b904f6e3180b8103b82564d1cdd08761a890db09344af1ffd2564418fafe6f02d174b958dc6f65a104f11eeca
data/LICENSE ADDED
@@ -0,0 +1,9 @@
1
+ Copyright (c) 2018 Trailblazer GmbH
2
+
3
+ Trailblazer is an Open Source project licensed under the terms of
4
+ the LGPLv3 license. Please see <http://www.gnu.org/licenses/lgpl-3.0.html>
5
+ for license text.
6
+
7
+ Trailblazer PRO has a commercial-friendly license allowing private forks
8
+ and modifications of Trailblazer. Please see http://trailblazer.to/pro for
9
+ more detail.
@@ -1,3 +1,8 @@
1
+ # 0.0.7
2
+
3
+ * Move `Activity::Trace` and `Activity::Present` from `activity` to `developer`.
4
+ * Remove global configurations and use `flow_options` to override defaults in `wtf?`.
5
+
1
6
  # 0.0.6
2
7
 
3
8
  * Remove ID extraction logic from `Generate`, this is done on the server-side.
@@ -12,7 +12,7 @@ module Trailblazer
12
12
 
13
13
  # Render an {Activity}'s circuit as a simple hash.
14
14
  def call(activity, **options)
15
- graph = Activity::Introspect::Graph(activity)
15
+ graph = Introspect::Graph(activity)
16
16
 
17
17
  circuit_hash(graph, **options)
18
18
  end
@@ -15,7 +15,7 @@ module Trailblazer
15
15
  module_function
16
16
 
17
17
  def call(operation, options = {style: :line})
18
- graph = Activity::Introspect::Graph(operation)
18
+ graph = Introspect::Graph(operation)
19
19
 
20
20
  rows = graph.collect do |node, i|
21
21
  next if node[:data][:stop_event] # DISCUSS: show this?
@@ -0,0 +1,59 @@
1
+ require 'trailblazer/activity'
2
+
3
+ module Trailblazer::Developer
4
+ module Trace
5
+ module Present
6
+ module_function
7
+
8
+ INDENTATION = " |".freeze
9
+ STEP_PREFIX = "-- ".freeze
10
+
11
+ def default_renderer(task_node:, **)
12
+ [ task_node[:level], %{#{task_node[:name]}} ]
13
+ end
14
+
15
+ def call(stack, level: 1, tree: [], renderer: method(:default_renderer), **options)
16
+ tree(stack.to_a, level, tree: tree, renderer: renderer, **options)
17
+ end
18
+
19
+ def tree(stack, level, tree:, renderer:, **options)
20
+ tree_for(stack, level, options.merge(tree: tree))
21
+
22
+ nodes = tree.each_with_index.map do |task_node, position|
23
+ renderer.(task_node: task_node, position: position, tree: tree)
24
+ end
25
+
26
+ render_tree_for(nodes)
27
+ end
28
+
29
+ def render_tree_for(nodes)
30
+ nodes.map { |level, node|
31
+ indentation = INDENTATION * (level -1)
32
+ indentation = indentation[0...-1] + "`" if level == 1 || /End./.match(node) # start or end step
33
+ indentation + STEP_PREFIX + node
34
+ }.join("\n")
35
+ end
36
+
37
+ def tree_for(stack, level, tree:, **options)
38
+ stack.each do |lvl| # always a Stack::Task[input, ..., output]
39
+ input, output, nested = Trace::Level.input_output_nested_for_level(lvl)
40
+
41
+ task = input.task
42
+
43
+ graph = Introspect::Graph(input.activity)
44
+
45
+ name = (node = graph.find { |node| node[:task] == task }) ? node[:id] : task
46
+ name ||= task # FIXME: bullshit
47
+
48
+ tree << { level: level, input: input, output: output, name: name, **options }
49
+
50
+ if nested.any? # nesting
51
+ tree_for(nested, level + 1, options.merge(tree: tree))
52
+ end
53
+
54
+ tree
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,147 @@
1
+ require 'trailblazer/activity'
2
+
3
+ module Trailblazer::Developer
4
+ module Trace
5
+
6
+ Activity = Trailblazer::Activity
7
+
8
+ class << self
9
+ # Public entry point to activate tracing when running {activity}.
10
+ def call(activity, (ctx, flow_options), circuit_options={})
11
+ activity, (ctx, flow_options), circuit_options = Trace.arguments_for_call( activity, [ctx, flow_options], circuit_options ) # only run once for the entire circuit!
12
+
13
+ signal, (ctx, flow_options) = Activity::TaskWrap.invoke(activity, [ctx, flow_options], circuit_options)
14
+
15
+ return flow_options[:stack], signal, [ctx, flow_options]
16
+ end
17
+
18
+ alias_method :invoke, :call
19
+
20
+ def arguments_for_call(activity, (options, flow_options), **circuit_options)
21
+ tracing_flow_options = {
22
+ stack: Trace::Stack.new,
23
+ }
24
+
25
+ tracing_circuit_options = {
26
+ wrap_runtime: ::Hash.new(Trace.merge_plan), # DISCUSS: this overrides existing {:wrap_runtime}.
27
+ }
28
+
29
+ return activity, [ options, tracing_flow_options.merge(flow_options) ], circuit_options.merge(tracing_circuit_options)
30
+ end
31
+ end
32
+
33
+ module_function
34
+ # Insertions for the trace tasks that capture the arguments just before calling the task,
35
+ # and before the TaskWrap is finished.
36
+ #
37
+ # @private
38
+ def merge_plan
39
+ Activity::TaskWrap::Pipeline::Merge.new(
40
+ [Activity::TaskWrap::Pipeline.method(:insert_before), "task_wrap.call_task", ["task_wrap.capture_args", Trace.method(:capture_args)]],
41
+ [Activity::TaskWrap::Pipeline.method(:append), nil, ["task_wrap.capture_return", Trace.method(:capture_return)]],
42
+ )
43
+ end
44
+
45
+ # taskWrap step to capture incoming arguments of a step.
46
+ def capture_args(wrap_config, original_args)
47
+ original_args = capture_for(wrap_config[:task], *original_args)
48
+
49
+ return wrap_config, original_args
50
+ end
51
+
52
+ # taskWrap step to capture outgoing arguments from a step.
53
+ def capture_return(wrap_config, original_args)
54
+ (original_options, original_flow_options, _) = original_args[0]
55
+
56
+ original_flow_options[:stack] << Entity::Output.new(
57
+ wrap_config[:task], {}, wrap_config[:return_signal]
58
+ ).freeze
59
+
60
+ original_flow_options[:stack].unindent!
61
+
62
+
63
+ return wrap_config, original_args
64
+ end
65
+
66
+ # It's important to understand that {flow[:stack]} is mutated by design. This is needed so
67
+ # in case of exceptions we still have a "global" trace - unfortunately Ruby doesn't allow
68
+ # us a better way.
69
+ def capture_for(task, (ctx, flow), activity:, **circuit_options)
70
+ flow[:stack].indent!
71
+
72
+ flow[:stack] << Entity::Input.new(
73
+ task, activity, [ctx, ctx.inspect]
74
+ ).freeze
75
+
76
+ return [ctx, flow], circuit_options.merge(activity: activity)
77
+ end
78
+
79
+ # Structures used in {capture_args} and {capture_return}.
80
+ # These get pushed onto one {Level} in a {Stack}.
81
+ #
82
+ # Level[
83
+ # Level[ ==> this is a scalar task
84
+ # Entity::Input
85
+ # Entity::Output
86
+ # ]
87
+ # Level[ ==> nested task
88
+ # Entity::Input
89
+ # Level[
90
+ # Entity::Input
91
+ # Entity::Output
92
+ # ]
93
+ # Entity::Output
94
+ # ]
95
+ # ]
96
+ Entity = Struct.new(:task, :activity, :data)
97
+ Entity::Input = Class.new(Entity)
98
+ Entity::Output = Class.new(Entity)
99
+
100
+ class Level < Array
101
+ def inspect
102
+ %{<Level>#{super}}
103
+ end
104
+
105
+ # @param level {Trace::Level}
106
+ def self.input_output_nested_for_level(level)
107
+ input = level[0]
108
+ output = level[-1]
109
+
110
+ output, nested = output.is_a?(Entity::Output) ? [output, level-[input, output]] : [nil, level[1..-1]]
111
+
112
+ return input, output, nested
113
+ end
114
+ end
115
+
116
+ # Mutable/stateful per design. We want a (global) stack!
117
+ class Stack
118
+ def initialize
119
+ @nested = Level.new
120
+ @stack = [ @nested ]
121
+ end
122
+
123
+ def indent!
124
+ current << indented = Level.new
125
+ @stack << indented
126
+ end
127
+
128
+ def unindent!
129
+ @stack.pop
130
+ end
131
+
132
+ def <<(args)
133
+ current << args
134
+ end
135
+
136
+ def to_a
137
+ @nested
138
+ end
139
+
140
+ private
141
+
142
+ def current
143
+ @stack.last
144
+ end
145
+ end # Stack
146
+ end
147
+ end
@@ -1,7 +1,7 @@
1
1
  module Trailblazer
2
2
  module Version
3
3
  module Developer
4
- VERSION = "0.0.6"
4
+ VERSION = "0.0.7"
5
5
  end
6
6
  end
7
7
  end
@@ -1,5 +1,3 @@
1
- require 'trailblazer/activity'
2
-
3
1
  module Trailblazer::Developer
4
2
  module_function
5
3
 
@@ -14,7 +12,15 @@ module Trailblazer::Developer
14
12
  module Wtf
15
13
  module_function
16
14
 
17
- COLOR_MAP = Trailblazer::Developer.config.trace_color_map
15
+ COLOR_MAP = { pass: :green, fail: :brown }
16
+
17
+ SIGNALS_MAP = {
18
+ 'Trailblazer::Activity::Right': :pass,
19
+ 'Trailblazer::Activity::FastTrack::PassFast': :pass,
20
+
21
+ 'Trailblazer::Activity::Left': :fail,
22
+ 'Trailblazer::Activity::FastTrack::FailFast': :fail,
23
+ }
18
24
 
19
25
  # Run {activity} with tracing enabled and inject a mutable {Stack} instance.
20
26
  # This allows to display the trace even when an exception happened
@@ -23,43 +29,50 @@ module Trailblazer::Developer
23
29
 
24
30
  # this instance gets mutated with every step. unfortunately, there is
25
31
  # no other way in Ruby to keep the trace even when an exception was thrown.
26
- stack = Trailblazer::Activity::Trace::Stack.new
27
-
28
- begin
29
- _returned_stack, *returned = Trailblazer::Activity::Trace.invoke(
30
- activity,
31
- [
32
- ctx,
33
- flow_options.merge(stack: stack)
34
- ],
35
- *args
36
- )
37
- puts Trailblazer::Activity::Trace::Present.(stack, renderer: method(:renderer))
38
-
39
- rescue => exception
40
- puts Trailblazer::Activity::Trace::Present.(stack, renderer: method(:renderer))
41
- raise(exception)
42
- end
32
+ stack = Trace::Stack.new
33
+
34
+ _returned_stack, *returned = Trace.invoke(
35
+ activity,
36
+ [
37
+ ctx,
38
+ flow_options.merge(stack: stack)
39
+ ],
40
+ *args
41
+ )
43
42
 
44
43
  returned
44
+ ensure
45
+ puts Trace::Present.(
46
+ stack,
47
+ renderer: method(:renderer),
48
+ color_map: COLOR_MAP.merge( flow_options[:color_map] || {} )
49
+ )
45
50
  end
46
51
 
47
52
  def renderer(task_node:, position:, tree:)
48
- if task_node[:output].nil? && tree[position.next].nil? # i.e. when exception raised
49
- return [ task_node[:level], %{#{fmt(fmt(task_node[:name], :red), :bold)}} ]
53
+ name, level, output, color_map = task_node.values_at(:name, :level, :output, :color_map)
54
+
55
+ if output.nil? && tree[position.next].nil? # i.e. when exception raised
56
+ return [ level, %{#{fmt(fmt(name, :red), :bold)}} ]
50
57
  end
51
58
 
52
- if task_node[:output].nil? # i.e. on entry/exit point of activity
53
- return [ task_node[:level], %{#{fmt(task_node[:name], COLOR_MAP.default)}} ]
59
+ if output.nil? # i.e. on entry/exit point of activity
60
+ return [ level, %{#{name}} ]
54
61
  end
55
62
 
56
- [ task_node[:level], %{#{fmt(task_node[:name], COLOR_MAP[task_node[:output].data])}} ]
63
+ [ level, %{#{fmt( name, color_map[ signal_of(output.data) ] )}} ]
57
64
  end
58
65
 
59
66
  def fmt(line, style)
67
+ return line unless style
60
68
  String.send(style, line)
61
69
  end
62
70
 
71
+ def signal_of(entity_output)
72
+ entity_klass = entity_output.is_a?(Class) ? entity_output : entity_output.class
73
+ SIGNALS_MAP[entity_klass.name.to_sym]
74
+ end
75
+
63
76
  # Stolen from https://stackoverflow.com/questions/1489183/colorized-ruby-output
64
77
  #
65
78
  # TODO: this is just prototyping
@@ -6,8 +6,10 @@ module Trailblazer
6
6
  end
7
7
  end
8
8
 
9
- require "trailblazer/developer/config"
10
9
  require "trailblazer/developer/wtf"
10
+ require "trailblazer/developer/trace"
11
+ require "trailblazer/developer/trace/present"
12
+ require "trailblazer/developer/introspect"
11
13
  require "trailblazer/developer/generate"
12
14
  require "trailblazer/developer/render/circuit"
13
15
  require "trailblazer/developer/render/linear"
@@ -10,7 +10,8 @@ Gem::Specification.new do |spec|
10
10
 
11
11
  spec.summary = "Developer tools for Trailblazer."
12
12
  spec.description = "Developer tools for Trailblazer: debugger, tracing, visual editor integration."
13
- spec.homepage = "http://trailblazer.to/gems/trailblazer/developer.html"
13
+ spec.homepage = "http://trailblazer.to"
14
+ spec.license = "LGPL-3.0"
14
15
 
15
16
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
16
17
  f.match(%r{^(test)/})
@@ -23,7 +24,7 @@ Gem::Specification.new do |spec|
23
24
  spec.add_development_dependency "rake"
24
25
  spec.add_development_dependency "rubocop"
25
26
 
26
- spec.add_dependency "trailblazer-activity", ">= 0.8.4"
27
+ spec.add_dependency "trailblazer-activity", ">= 0.10.0"
27
28
  spec.add_dependency "trailblazer-activity-dsl-linear"
28
29
  spec.add_dependency "representable"
29
30
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trailblazer-developer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
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 00:00:00.000000000 Z
11
+ date: 2019-09-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - ">="
88
88
  - !ruby/object:Gem::Version
89
- version: 0.8.4
89
+ version: 0.10.0
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
- version: 0.8.4
96
+ version: 0.10.0
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: trailblazer-activity-dsl-linear
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -133,6 +133,7 @@ files:
133
133
  - ".rubocop.yml"
134
134
  - ".travis.yml"
135
135
  - Gemfile
136
+ - LICENSE
136
137
  - README.md
137
138
  - Rakefile
138
139
  - bin/console
@@ -142,16 +143,18 @@ files:
142
143
  - lib/trailblazer/developer/CHANGES.md
143
144
  - lib/trailblazer/developer/activity.rb
144
145
  - lib/trailblazer/developer/client.rb
145
- - lib/trailblazer/developer/config.rb
146
146
  - lib/trailblazer/developer/generate.rb
147
147
  - lib/trailblazer/developer/render/circuit.rb
148
148
  - lib/trailblazer/developer/render/linear.rb
149
+ - lib/trailblazer/developer/trace.rb
150
+ - lib/trailblazer/developer/trace/present.rb
149
151
  - lib/trailblazer/developer/version.rb
150
152
  - lib/trailblazer/developer/wtf.rb
151
153
  - lib/trailblazer/diagram/bpmn.rb
152
154
  - trailblazer-developer.gemspec
153
- homepage: http://trailblazer.to/gems/trailblazer/developer.html
154
- licenses: []
155
+ homepage: http://trailblazer.to
156
+ licenses:
157
+ - LGPL-3.0
155
158
  metadata: {}
156
159
  post_install_message:
157
160
  rdoc_options: []
@@ -169,7 +172,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
169
172
  version: '0'
170
173
  requirements: []
171
174
  rubyforge_project:
172
- rubygems_version: 2.7.3
175
+ rubygems_version: 2.7.6
173
176
  signing_key:
174
177
  specification_version: 4
175
178
  summary: Developer tools for Trailblazer.
@@ -1,30 +0,0 @@
1
- module Trailblazer::Developer
2
- # {config} gives global settings for Developer
3
- # Trailblazer::Developer.configure do |config|
4
- # config.trace_color_map[Trailblazer::Activity::Right] = :green
5
- # config.trace_color_map.default = :green
6
- # end
7
-
8
- class << self
9
- def configure
10
- yield config
11
- end
12
-
13
- def config
14
- @config ||= Config.new
15
- end
16
- end
17
-
18
- class Config
19
- attr_reader :trace_color_map
20
-
21
- def initialize
22
- @trace_color_map = {
23
- Trailblazer::Activity::Right => :green,
24
- Trailblazer::Activity::Left => :brown
25
- }
26
-
27
- @trace_color_map.default = :green
28
- end
29
- end
30
- end