trailblazer-activity 0.12.2 → 0.13.0

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: 64e6b7c70557dea00024b9e16b1d85ee3046589a5b759028a2178cdd6da99231
4
- data.tar.gz: 2283d2744d77ca89de067f1a368c98ddc60b4e4ca39337b59066d35f642a7c65
3
+ metadata.gz: 36888239a75b308074977ecb9637e421940f63a53fdafbadb5a65106152fc550
4
+ data.tar.gz: 3aff2a8fb3da591b98f72f387555791c8273dc02968b68a5f4eb8d59a69f7e45
5
5
  SHA512:
6
- metadata.gz: c9a1c011210c61b7e1ae55df77d003e4029160968093b3c71c73ccd65e460bdb911a97a016b7c524f9d3806074816f195a85f8e4e66b67245f670d7c69650417
7
- data.tar.gz: cc45abe8914b199fa98e31e0e6e9e9b9582e4e097c296f3407f3e365851813a632eb45133f37bf95c71212c08c15e0deafc723d952d1f00bf6e8087035bd07cd
6
+ metadata.gz: bffee75027f1af8e1dd87487f07505bc5e8238e62eb67ffc1a128f90fbaeb5d4feadcbac2294991ef69febd71245292dd39128fd52e78bba11a9be8afce1cdf9
7
+ data.tar.gz: 8ac7bc2b36e8db2349134ce935d1da0881a749c881dca6703c1ed192862d526a734de5da8c956f59b60293300f3dd3fabb05c0e21fbd5187cf2a53b09992c368
data/CHANGES.md CHANGED
@@ -1,3 +1,11 @@
1
+ # 0.13.0
2
+
3
+ * Removed `TaskWrap::Inject::Defaults`. This is now implemented through `dsl`'s `:inject` option.
4
+ * Removed `TaskWrap::VariableMapping.Extension`.
5
+ * Renamed private `TaskWrap::VariableMapping.merge_for` to `.merge_instructions_for` as there's no {Merge} instance, yet.
6
+ * Extract invocation logic in `TaskBuilder::Task` into `Task#call_option`.
7
+ * Add `TaskWrap::Pipeline::prepend`.
8
+
1
9
  # 0.12.2
2
10
 
3
11
  * Use extracted `trailblazer-option`.
data/README.md CHANGED
@@ -2,15 +2,15 @@
2
2
 
3
3
  Implements Intermediate, Implementation and compiler
4
4
 
5
- The `activity` gem brings a light-weight DSL to define business processes, and the runtime logic to run those activities.
5
+ The `activity` gem implements the runtime logic to invoke a new abstraction called "activities". Ideally, activities are defined using the [`dsl-linear` DSL gem](https://github.com/trailblazer/trailblazer-activity-dsl-linear).
6
6
 
7
7
  A process is a set of arbitrary pieces of logic you define, chained together and put into a meaningful context by an activity. Activity lets you focus on the implementation of steps while Trailblazer takes care of the control flow.
8
8
 
9
- Please find the [full documentation on the Trailblazer website](https://2019.trailblazer.to/2.1/docs/activity.html). [Note that the docs are WIP.]
9
+ Please find the [full documentation on the Trailblazer website](https://trailblazer.to/2.1/docs/activity.html).
10
10
 
11
11
  ## Example
12
12
 
13
- In conjunction with [`dsl-linear`](https://github.com/trailblazer/trailblazer-activity-dsl-linear), the `activity` gem provides three default patterns to model processes: `Path`, `Railway` and `FastTrack`. Here's an example of what a railway activity could look like, along with some more complex connections (you can read more about Railway strategy in the [docs](https://2019.trailblazer.to/2.1/docs/activity.html#activity-strategy-railway)).
13
+ In conjunction with [`dsl-linear`](https://github.com/trailblazer/trailblazer-activity-dsl-linear), the `activity` gem provides three default patterns to model processes: `Path`, `Railway` and `FastTrack`. Here's an example of what a railway activity could look like, along with some more complex connections (you can read more about Railway strategy in the [docs](https://trailblazer.to/2.1/docs/activity.html#activity-strategy-railway)).
14
14
 
15
15
  ```ruby
16
16
  require "trailblazer-activity"
@@ -78,15 +78,15 @@ With Activity, modeling business processes turns out to be ridiculously simple:
78
78
 
79
79
  ## Operation
80
80
 
81
- Trailblazer's [`Operation`](https://2019.trailblazer.to/2.1/docs/operation.html#operation-overview) internally uses an activity to model the processes.
81
+ Trailblazer's [`Operation`](https://trailblazer.to/2.1/docs/operation.html#operation-overview) internally uses an activity to model the processes.
82
82
 
83
83
  ## Workflow
84
- Activities can be formed into bigger compounds and using workflow, you can build long-running processes such as a moderated blog post or a parcel delivery. Also, you don't have to use the DSL but can use the [`editor`](https://2019.trailblazer.to/2.1/docs/pro.html#pro-editor)instead(cool for more complex, long-running flows). Here comes a sample screenshot.
84
+ Activities can be formed into bigger compounds and using workflow, you can build long-running processes such as a moderated blog post or a parcel delivery. Also, you don't have to use the DSL but can use the [`editor`](https://trailblazer.to/2.1/docs/pro.html#pro-editor)instead(cool for more complex, long-running flows). Here comes a sample screenshot.
85
85
 
86
- <img src="http://2019.trailblazer.to/2.1/dist/img/flow.png">
86
+ <img src="http://trailblazer.to/2.1/dist/img/flow.png">
87
87
 
88
88
  ## License
89
89
 
90
90
  © Copyright 2018, Trailblazer GmbH
91
91
 
92
- Licensed under the LGPLv3 license. We also offer a commercial-friendly [license](https://2019.trailblazer.to/2.1/docs/pro.html#pro-license).
92
+ Licensed under the LGPLv3 license. We also offer a commercial-friendly [license](https://trailblazer.to/2.1/docs/pro.html#pro-license).
@@ -18,17 +18,20 @@ module Trailblazer
18
18
  end
19
19
  end
20
20
 
21
+ # Wraps a {task} (that usually expects the task interface) into a circuit interface
22
+ # that can be used directly in a {Circuit}.
23
+ # We expect {task} to be exposing an {Option()} interface when calling it.
21
24
  class Task
22
25
  def initialize(task, user_proc)
23
26
  @task = task
24
27
  @user_proc = user_proc
25
-
26
28
  freeze
27
29
  end
28
30
 
29
- def call( (ctx, flow_options), **circuit_options )
31
+ def call((ctx, flow_options), **circuit_options)
30
32
  # Execute the user step with TRB's kw args.
31
- result = @task.(ctx, keyword_arguments: ctx.to_hash, **circuit_options) # circuit_options contains :exec_context.
33
+ # {@task} is/implements {Trailblazer::Option} interface.
34
+ result = call_option(@task, [ctx, flow_options], **circuit_options)
32
35
 
33
36
  # Return an appropriate signal which direction to go next.
34
37
  signal = Activity::TaskBuilder.binary_signal_for(result, Activity::Right, Activity::Left)
@@ -36,6 +39,11 @@ module Trailblazer
36
39
  return signal, [ctx, flow_options]
37
40
  end
38
41
 
42
+ # Invoke the original {user_proc} that is wrapped in an {Option()}.
43
+ private def call_option(task_with_option_interface, (ctx, _flow_options), **circuit_options)
44
+ task_with_option_interface.(ctx, keyword_arguments: ctx.to_hash, **circuit_options) # circuit_options contains :exec_context.
45
+ end
46
+
39
47
  def inspect # TODO: make me private!
40
48
  %{#<Trailblazer::Activity::TaskBuilder::Task user_proc=#{Trailblazer::Activity::Introspect.render_task(@user_proc)}>}
41
49
  end
@@ -17,7 +17,7 @@ class Trailblazer::Activity
17
17
  attr_reader :sequence
18
18
 
19
19
  def self.insert_before(pipe, before_id, insertion)
20
- index = pipe.sequence.find_index { |(id, _)| id == before_id }
20
+ index = find_index(pipe, before_id)
21
21
 
22
22
  seq = pipe.sequence.dup
23
23
 
@@ -25,18 +25,32 @@ class Trailblazer::Activity
25
25
  end
26
26
 
27
27
  def self.insert_after(pipe, after_id, insertion)
28
- index = pipe.sequence.find_index { |(id, _)| id == after_id }
28
+ index = find_index(pipe, after_id)
29
29
 
30
30
  seq = pipe.sequence.dup
31
31
 
32
32
  Pipeline.new(seq.insert(index+1, insertion))
33
33
  end
34
34
 
35
- def self.append(pipe, _, insertion) # TODO: test me.
35
+ def self.append(pipe, _, insertion)
36
36
  Pipeline.new(pipe.sequence + [insertion])
37
37
  end
38
38
 
39
- # Merges {extension_rows} into the {task_wrap_pipeline}.
39
+ def self.prepend(pipe, insertion_id, insertion, replace: 0)
40
+ return Pipeline.new(insertion.to_a + pipe.sequence) if insertion_id.nil?
41
+
42
+ index = find_index(pipe, insertion_id)
43
+
44
+ Pipeline.new(pipe.sequence[0..index-1] + insertion.to_a + pipe.sequence[index+replace..-1])
45
+ end
46
+
47
+ # @private
48
+ def self.find_index(pipe, id)
49
+ index = pipe.sequence.find_index { |(seq_id, _)| seq_id == id }
50
+ end
51
+
52
+
53
+ # Merges {extension_rows} into the {Pipeline} instance.
40
54
  # This is usually used in step extensions or at runtime for {wrap_runtime}.
41
55
  #
42
56
  # {Extension} API
@@ -5,17 +5,11 @@ class Trailblazer::Activity
5
5
  # translate them into a {DSL::Extension}.
6
6
  #
7
7
  # Note that the two options are not the only way to create filters, you can use the
8
- # more low-level {Scoped()} etc., too, and write your own filter logic.
8
+ # more low-level {Scoped()} from the `dsl` gem, too, and write your own filter logic.
9
9
  module VariableMapping
10
- # The taskWrap extension that's included into the static taskWrap for a task.
11
- def self.Extension(input, output, id: input.object_id)
12
- Trailblazer::Activity::TaskWrap::Extension(
13
- merge: merge_for(input, output, id: id),
14
- )
15
- end
16
-
17
- # DISCUSS: do we want the automatic wrapping of {input} and {output}?
18
- def self.merge_for(input, output, id:) # TODO: rename
10
+ # Places filters before/after the {call_task}.
11
+ # Note that {input} and {output} are automatically wrapped.
12
+ def self.merge_instructions_for(input, output, id:)
19
13
  [
20
14
  [TaskWrap::Pipeline.method(:insert_before), "task_wrap.call_task", ["task_wrap.input", TaskWrap::Input.new(input, id: id)]],
21
15
  [TaskWrap::Pipeline.method(:insert_after), "task_wrap.call_task", ["task_wrap.output", TaskWrap::Output.new(output, id: id)]],
@@ -37,9 +31,10 @@ class Trailblazer::Activity
37
31
  @id = id
38
32
  end
39
33
 
40
- # {input.call()} is invoked in the circuit.
41
- # `original_args` are the actual args passed to the wrapped task: [ [ctx, ..], circuit_options ]
42
- #
34
+ # {input.call()} is invoked in the taskWrap pipeline.
35
+ # {original_args} are the actual args passed to the wrapped task: [ [ctx, ..], circuit_options ]
36
+ # We now swap the ctx in {original_args} and our filtered one. The original "outside" ctx is keyed in
37
+ # {wrap_ctx} with the filter ID.
43
38
  def call(wrap_ctx, original_args)
44
39
  # let user compute new ctx for the wrapped task.
45
40
  input_ctx = apply_filter(*original_args)
@@ -71,9 +66,7 @@ class Trailblazer::Activity
71
66
 
72
67
  # Runs your filter and replaces the ctx in `wrap_ctx[:return_args]` with the filtered one.
73
68
  def call(wrap_ctx, original_args)
74
- (original_ctx, original_flow_options), original_circuit_options = original_args
75
-
76
- return_args = wrap_ctx[:return_args]
69
+ (original_ctx, _original_flow_options), original_circuit_options = original_args
77
70
 
78
71
  returned_ctx, returned_flow_options = wrap_ctx[:return_args] # this is the Context returned from {call}ing the wrapped user task.
79
72
  original_ctx = wrap_ctx[@id] # grab the original ctx from before which was set in the {:input} filter.
@@ -14,7 +14,8 @@ module Trailblazer
14
14
 
15
15
  # Compute runtime arguments necessary to execute a taskWrap per task of the activity.
16
16
  # This method is the top-level entry, called only once for the entire activity graph.
17
- def invoke(activity, args, wrap_runtime: {}, wrap_static: initial_wrap_static, **circuit_options)
17
+ # [:wrap_static] The taskWrap used for the topmost activity/operation.
18
+ def invoke(activity, args, wrap_runtime: {}, wrap_static: initial_wrap_static, **circuit_options) # FIXME: why do we need this method?
18
19
  circuit_options = circuit_options.merge(
19
20
  runner: TaskWrap::Runner,
20
21
  wrap_runtime: wrap_runtime,
@@ -24,7 +25,7 @@ module Trailblazer
24
25
  )
25
26
 
26
27
  # signal, (ctx, flow), circuit_options =
27
- Runner.(activity, args, **circuit_options)
28
+ TaskWrap::Runner.(activity, args, **circuit_options)
28
29
  end
29
30
 
30
31
  # {:extension} API
@@ -62,4 +63,3 @@ require "trailblazer/activity/task_wrap/pipeline"
62
63
  require "trailblazer/activity/task_wrap/call_task"
63
64
  require "trailblazer/activity/task_wrap/runner"
64
65
  require "trailblazer/activity/task_wrap/variable_mapping"
65
- require "trailblazer/activity/task_wrap/inject"
@@ -1,7 +1,7 @@
1
1
  module Trailblazer
2
2
  module Version
3
3
  module Activity
4
- VERSION = '0.12.2'.freeze
4
+ VERSION = '0.13.0'.freeze
5
5
  end
6
6
  end
7
7
  end
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.12.2
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Sutterer
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-12 00:00:00.000000000 Z
11
+ date: 2021-12-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: trailblazer-context
@@ -108,7 +108,7 @@ dependencies:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: 0.0.7
111
- description:
111
+ description:
112
112
  email:
113
113
  - apotonick@gmail.com
114
114
  executables: []
@@ -135,7 +135,6 @@ files:
135
135
  - lib/trailblazer/activity/task_builder.rb
136
136
  - lib/trailblazer/activity/task_wrap.rb
137
137
  - lib/trailblazer/activity/task_wrap/call_task.rb
138
- - lib/trailblazer/activity/task_wrap/inject.rb
139
138
  - lib/trailblazer/activity/task_wrap/pipeline.rb
140
139
  - lib/trailblazer/activity/task_wrap/runner.rb
141
140
  - lib/trailblazer/activity/task_wrap/variable_mapping.rb
@@ -146,7 +145,7 @@ homepage: http://trailblazer.to
146
145
  licenses:
147
146
  - LGPL-3.0
148
147
  metadata: {}
149
- post_install_message:
148
+ post_install_message:
150
149
  rdoc_options: []
151
150
  require_paths:
152
151
  - lib
@@ -161,8 +160,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
161
160
  - !ruby/object:Gem::Version
162
161
  version: '0'
163
162
  requirements: []
164
- rubygems_version: 3.0.8
165
- signing_key:
163
+ rubygems_version: 3.2.3
164
+ signing_key:
166
165
  specification_version: 4
167
166
  summary: Runtime code for Trailblazer activities.
168
167
  test_files: []
@@ -1,39 +0,0 @@
1
- class Trailblazer::Activity
2
- module TaskWrap
3
- # Allows to inject attributes for a task and defaults them if not.
4
- # Per default, the defaulting is scoped, meaning only the task will see it.
5
- module Inject
6
- module Defaults
7
- module_function
8
-
9
- def Extension(defaults)
10
- # Returns new ctx.
11
- input = ->((original_ctx, flow_options), circuit_options) do
12
- defaulted_options = defaults_for(defaults, original_ctx)
13
-
14
- ctx = original_ctx.merge(defaulted_options)
15
-
16
- Trailblazer::Context(ctx, {}, flow_options[:context_options])
17
- end
18
-
19
- output = ->(new_ctx, (original_ctx, _flow_options), _circuit_options) { # FIXME: use Unscope
20
- _, mutable_data = new_ctx.decompose
21
-
22
- # we are only interested in the {mutable_data} part since the disposed part
23
- # represents the injected/defaulted data.
24
- original_ctx.merge(mutable_data)
25
- }
26
-
27
- VariableMapping::Extension(input, output, id: input)
28
- end
29
-
30
- # go through all defaultable options and default them if appropriate.
31
- def defaults_for(defaults, original_ctx)
32
- Hash[
33
- defaults.collect { |k, v| [k, original_ctx[k] || v] } # FIXME: doesn't allow {false/nil} currently.
34
- ]
35
- end
36
- end
37
- end # Inject
38
- end
39
- end