trailblazer-activity 0.12.2 → 0.13.0

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
  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