cmdx 1.5.1 → 1.6.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 +4 -4
- data/CHANGELOG.md +12 -0
- data/LLM.md +16 -5
- data/README.md +4 -5
- data/docs/getting_started.md +11 -2
- data/docs/internationalization.md +4 -2
- data/docs/workflows.md +1 -1
- data/lib/cmdx/{worker.rb → executor.rb} +10 -10
- data/lib/cmdx/pipeline.rb +99 -0
- data/lib/cmdx/task.rb +1 -1
- data/lib/cmdx/version.rb +1 -1
- data/lib/cmdx/workflow.rb +14 -32
- metadata +4 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ef05af7473358890c311d872369f870fbaa7ff7bf2fd6d6d14cddd9c9dc80aec
|
4
|
+
data.tar.gz: 8e1c20c5991d453f947ed5aea44099c9c05861ad11637b27eb02bb5baea4e4f2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c59da9cc99292e6241bf9d7fabb91cc00887a6b8a4cd18950c22a495a1adfdc32a769194818944726da0e732e8fb23c842c7086d67ea451f2556a31c4f3a5ef2
|
7
|
+
data.tar.gz: 89d64b25f51d583605960e19d9b08b366dc4269b5c2ca07cddf562714aaf2cc4c0d9f1a06bbae42ed0ba9ed536715030c4d79dbf8c486305bd4891c331a5107d
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
|
7
7
|
## [TODO]
|
8
8
|
|
9
|
+
## [1.6.0] - 2025-08-22
|
10
|
+
|
11
|
+
### Changes
|
12
|
+
- Rename `Worker` class to `Executor`
|
13
|
+
- Move workflow `work` logic into `Pipeline`
|
14
|
+
- Add workflow task `:breakpoints`
|
15
|
+
|
16
|
+
## [1.5.2] - 2025-08-22
|
17
|
+
|
18
|
+
### Changes
|
19
|
+
- Rename workflow `execution_groups` attribute to `pipeline`
|
20
|
+
|
9
21
|
## [1.5.1] - 2025-08-21
|
10
22
|
|
11
23
|
### Changes
|
data/LLM.md
CHANGED
@@ -44,11 +44,20 @@ Globally these settings are initialized with sensible defaults.
|
|
44
44
|
|
45
45
|
### Breakpoints
|
46
46
|
|
47
|
-
|
47
|
+
Raise `CMDx::Fault` when a task called with `execute!` returns a matching status.
|
48
48
|
|
49
49
|
```ruby
|
50
50
|
CMDx.configure do |config|
|
51
|
-
|
51
|
+
# String or Array[String]
|
52
|
+
config.task_breakpoints = "failed"
|
53
|
+
end
|
54
|
+
```
|
55
|
+
|
56
|
+
Workflow breakpoints stops execution and of workflow pipeline on the first task that returns a matching status and throws its `CMDx::Fault`.
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
CMDx.configure do |config|
|
60
|
+
# String or Array[String]
|
52
61
|
config.workflow_breakpoints = ["skipped", "failed"]
|
53
62
|
end
|
54
63
|
```
|
@@ -2785,8 +2794,7 @@ CMDx provides comprehensive internationalization support for all error messages,
|
|
2785
2794
|
|
2786
2795
|
## Localization
|
2787
2796
|
|
2788
|
-
|
2789
|
-
> CMDx automatically localizes all error messages based on the `I18n.locale` setting.
|
2797
|
+
CMDx automatically localizes all error messages based on the `I18n.locale` setting.
|
2790
2798
|
|
2791
2799
|
```ruby
|
2792
2800
|
class ProcessQuote < CMDx::Task
|
@@ -2803,6 +2811,9 @@ I18n.with_locale(:fr) do
|
|
2803
2811
|
end
|
2804
2812
|
```
|
2805
2813
|
|
2814
|
+
> [!TIP]
|
2815
|
+
> CMDx supports 85+ locales via the [cmdx-i18n](https://github.com/drexed/cmdx-i18n) gem.
|
2816
|
+
|
2806
2817
|
---
|
2807
2818
|
|
2808
2819
|
url: https://github.com/drexed/cmdx/blob/main/docs/deprecation.md
|
@@ -2964,7 +2975,7 @@ Workflow orchestrates sequential execution of multiple tasks in a linear pipelin
|
|
2964
2975
|
|
2965
2976
|
## Declarations
|
2966
2977
|
|
2967
|
-
Tasks execute in declaration order (FIFO). The workflow context propagates to each task, allowing access to data from previous executions.
|
2978
|
+
Tasks execute sequentially in declaration order (FIFO). The workflow context propagates to each task, allowing access to data from previous executions.
|
2968
2979
|
|
2969
2980
|
> [!IMPORTANT]
|
2970
2981
|
> Do **NOT** define a `work` method in workflow tasks. The included module automatically provides the execution logic.
|
data/README.md
CHANGED
@@ -122,13 +122,12 @@ end
|
|
122
122
|
|
123
123
|
## Ecosystem
|
124
124
|
|
125
|
+
- [cmdx-i18n](https://github.com/drexed/cmdx-i18n) - 85+ translations
|
126
|
+
|
125
127
|
The following gems are currently under development:
|
126
128
|
|
127
|
-
- `cmdx-
|
128
|
-
- `cmdx-
|
129
|
-
- `cmdx-minitest` Minitest matchers
|
130
|
-
- `cmdx-jobs` Background job integrations
|
131
|
-
- `cmdx-parallel` Parallel workflow task execution
|
129
|
+
- `cmdx-testing` - RSpec and Minitest matchers
|
130
|
+
- `cmdx-parallel` - Parallel workflow task execution
|
132
131
|
|
133
132
|
## Development
|
134
133
|
|
data/docs/getting_started.md
CHANGED
@@ -54,11 +54,20 @@ Globally these settings are initialized with sensible defaults.
|
|
54
54
|
|
55
55
|
### Breakpoints
|
56
56
|
|
57
|
-
|
57
|
+
Raise `CMDx::Fault` when a task called with `execute!` returns a matching status.
|
58
58
|
|
59
59
|
```ruby
|
60
60
|
CMDx.configure do |config|
|
61
|
-
|
61
|
+
# String or Array[String]
|
62
|
+
config.task_breakpoints = "failed"
|
63
|
+
end
|
64
|
+
```
|
65
|
+
|
66
|
+
Workflow breakpoints stops execution and of workflow pipeline on the first task that returns a matching status and throws its `CMDx::Fault`.
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
CMDx.configure do |config|
|
70
|
+
# String or Array[String]
|
62
71
|
config.workflow_breakpoints = ["skipped", "failed"]
|
63
72
|
end
|
64
73
|
```
|
@@ -8,8 +8,7 @@ CMDx provides comprehensive internationalization support for all error messages,
|
|
8
8
|
|
9
9
|
## Localization
|
10
10
|
|
11
|
-
|
12
|
-
> CMDx automatically localizes all error messages based on the `I18n.locale` setting.
|
11
|
+
CMDx automatically localizes all error messages based on the `I18n.locale` setting.
|
13
12
|
|
14
13
|
```ruby
|
15
14
|
class ProcessQuote < CMDx::Task
|
@@ -26,6 +25,9 @@ I18n.with_locale(:fr) do
|
|
26
25
|
end
|
27
26
|
```
|
28
27
|
|
28
|
+
> [!TIP]
|
29
|
+
> CMDx supports 85+ locales via the [cmdx-i18n](https://github.com/drexed/cmdx-i18n) gem.
|
30
|
+
|
29
31
|
---
|
30
32
|
|
31
33
|
- **Prev:** [Logging](logging.md)
|
data/docs/workflows.md
CHANGED
@@ -15,7 +15,7 @@ Workflow orchestrates sequential execution of multiple tasks in a linear pipelin
|
|
15
15
|
|
16
16
|
## Declarations
|
17
17
|
|
18
|
-
Tasks execute in declaration order (FIFO). The workflow context propagates to each task, allowing access to data from previous executions.
|
18
|
+
Tasks execute sequentially in declaration order (FIFO). The workflow context propagates to each task, allowing access to data from previous executions.
|
19
19
|
|
20
20
|
> [!IMPORTANT]
|
21
21
|
> Do **NOT** define a `work` method in workflow tasks. The included module automatically provides the execution logic.
|
@@ -3,19 +3,19 @@
|
|
3
3
|
module CMDx
|
4
4
|
# Executes CMDx tasks with middleware support, error handling, and lifecycle management.
|
5
5
|
#
|
6
|
-
# The
|
6
|
+
# The Executor class is responsible for orchestrating task execution, including
|
7
7
|
# pre-execution validation, execution with middleware, post-execution callbacks,
|
8
8
|
# and proper error handling for different types of failures.
|
9
|
-
class
|
9
|
+
class Executor
|
10
10
|
|
11
11
|
attr_reader :task
|
12
12
|
|
13
13
|
# @param task [CMDx::Task] The task to execute
|
14
14
|
#
|
15
|
-
# @return [CMDx::
|
15
|
+
# @return [CMDx::Executor] A new executor instance
|
16
16
|
#
|
17
17
|
# @example
|
18
|
-
#
|
18
|
+
# executor = CMDx::Executor.new(my_task)
|
19
19
|
def initialize(task)
|
20
20
|
@task = task
|
21
21
|
end
|
@@ -30,8 +30,8 @@ module CMDx
|
|
30
30
|
# @raise [StandardError] When raise is true and execution fails
|
31
31
|
#
|
32
32
|
# @example
|
33
|
-
# CMDx::
|
34
|
-
# CMDx::
|
33
|
+
# CMDx::Executor.execute(my_task)
|
34
|
+
# CMDx::Executor.execute(my_task, raise: true)
|
35
35
|
def self.execute(task, raise: false)
|
36
36
|
instance = new(task)
|
37
37
|
raise ? instance.execute! : instance.execute
|
@@ -42,8 +42,8 @@ module CMDx
|
|
42
42
|
# @return [CMDx::Result] The execution result
|
43
43
|
#
|
44
44
|
# @example
|
45
|
-
#
|
46
|
-
# result =
|
45
|
+
# executor = CMDx::Executor.new(my_task)
|
46
|
+
# result = executor.execute
|
47
47
|
def execute
|
48
48
|
task.class.settings[:middlewares].call!(task) do
|
49
49
|
pre_execution!
|
@@ -69,8 +69,8 @@ module CMDx
|
|
69
69
|
# @raise [StandardError] When execution fails
|
70
70
|
#
|
71
71
|
# @example
|
72
|
-
#
|
73
|
-
# result =
|
72
|
+
# executor = CMDx::Executor.new(my_task)
|
73
|
+
# result = executor.execute!
|
74
74
|
def execute!
|
75
75
|
task.class.settings[:middlewares].call!(task) do
|
76
76
|
pre_execution!
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CMDx
|
4
|
+
# Executes workflows by processing task groups with conditional logic and breakpoint handling.
|
5
|
+
# The Pipeline class manages the execution flow of workflow tasks, evaluating conditions
|
6
|
+
# and handling breakpoints that can interrupt execution at specific task statuses.
|
7
|
+
class Pipeline
|
8
|
+
|
9
|
+
# @return [Workflow] The workflow instance being executed
|
10
|
+
attr_reader :workflow
|
11
|
+
|
12
|
+
# @param workflow [Workflow] The workflow to execute
|
13
|
+
#
|
14
|
+
# @return [Pipeline] A new pipeline instance
|
15
|
+
#
|
16
|
+
# @example
|
17
|
+
# pipeline = Pipeline.new(my_workflow)
|
18
|
+
def initialize(workflow)
|
19
|
+
@workflow = workflow
|
20
|
+
end
|
21
|
+
|
22
|
+
# Executes a workflow using a new pipeline instance.
|
23
|
+
#
|
24
|
+
# @param workflow [Workflow] The workflow to execute
|
25
|
+
#
|
26
|
+
# @return [void]
|
27
|
+
#
|
28
|
+
# @example
|
29
|
+
# Pipeline.execute(my_workflow)
|
30
|
+
def self.execute(workflow)
|
31
|
+
new(workflow).execute
|
32
|
+
end
|
33
|
+
|
34
|
+
# Executes the workflow by processing all task groups in sequence.
|
35
|
+
# Each group is evaluated against its conditions, and breakpoints are checked
|
36
|
+
# after each task execution to determine if workflow should continue or halt.
|
37
|
+
#
|
38
|
+
# @return [void]
|
39
|
+
#
|
40
|
+
# @example
|
41
|
+
# pipeline = Pipeline.new(my_workflow)
|
42
|
+
# pipeline.execute
|
43
|
+
def execute
|
44
|
+
workflow.class.pipeline.each do |group|
|
45
|
+
next unless Utils::Condition.evaluate(workflow, group.options, workflow)
|
46
|
+
|
47
|
+
breakpoints = group.options[:breakpoints] ||
|
48
|
+
workflow.class.settings[:breakpoints] ||
|
49
|
+
workflow.class.settings[:workflow_breakpoints]
|
50
|
+
breakpoints = Array(breakpoints).map(&:to_s).uniq
|
51
|
+
|
52
|
+
execute_group_tasks(group, breakpoints)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
# Executes tasks within a group using the configured execution strategy.
|
59
|
+
# Override this method to implement custom execution strategies like parallel
|
60
|
+
# processing or conditional task execution.
|
61
|
+
#
|
62
|
+
# @param group [ExecutionGroup] The group of tasks to execute
|
63
|
+
# @param breakpoints [Array<String>] Breakpoint statuses that trigger workflow interruption
|
64
|
+
#
|
65
|
+
# @return [void]
|
66
|
+
#
|
67
|
+
# @example
|
68
|
+
# def execute_group_tasks(group, breakpoints)
|
69
|
+
# # Custom parallel execution strategy
|
70
|
+
# group.tasks.map { |task| Thread.new { task.execute(workflow.context) } }
|
71
|
+
# end
|
72
|
+
def execute_group_tasks(group, breakpoints)
|
73
|
+
# NOTE: Override this method to introduce alternative execution strategies
|
74
|
+
execute_tasks_sequentially(group, breakpoints)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Executes tasks sequentially within a group, checking breakpoints after each task.
|
78
|
+
# If a task result status matches a breakpoint, the workflow is interrupted.
|
79
|
+
#
|
80
|
+
# @param group [ExecutionGroup] The group of tasks to execute
|
81
|
+
# @param breakpoints [Array<String>] Breakpoint statuses that trigger workflow interruption
|
82
|
+
#
|
83
|
+
# @return [void]
|
84
|
+
#
|
85
|
+
# @raise [HaltError] When a task result status matches a breakpoint
|
86
|
+
#
|
87
|
+
# @example
|
88
|
+
# execute_tasks_sequentially(group, ["failed", "skipped"])
|
89
|
+
def execute_tasks_sequentially(group, breakpoints)
|
90
|
+
group.tasks.each do |task|
|
91
|
+
task_result = task.execute(workflow.context)
|
92
|
+
next unless breakpoints.include?(task_result.status)
|
93
|
+
|
94
|
+
workflow.throw!(task_result)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
data/lib/cmdx/task.rb
CHANGED
@@ -200,7 +200,7 @@ module CMDx
|
|
200
200
|
# result = task.execute
|
201
201
|
# result = task.execute(raise: true)
|
202
202
|
def execute(raise: false)
|
203
|
-
|
203
|
+
Executor.execute(self, raise:)
|
204
204
|
end
|
205
205
|
|
206
206
|
# @raise [UndefinedMethodError] Always raised as this method must be overridden
|
data/lib/cmdx/version.rb
CHANGED
data/lib/cmdx/workflow.rb
CHANGED
@@ -35,10 +35,10 @@ module CMDx
|
|
35
35
|
# include CMDx::Workflow
|
36
36
|
# task Task1
|
37
37
|
# task Task2
|
38
|
-
# puts
|
38
|
+
# puts pipeline.size # => 2
|
39
39
|
# end
|
40
|
-
def
|
41
|
-
@
|
40
|
+
def pipeline
|
41
|
+
@pipeline ||= []
|
42
42
|
end
|
43
43
|
|
44
44
|
# Adds multiple tasks to the workflow with optional configuration.
|
@@ -56,7 +56,7 @@ module CMDx
|
|
56
56
|
# tasks ValidateTask, ProcessTask, NotifyTask, breakpoints: [:failure, :halt]
|
57
57
|
# end
|
58
58
|
def tasks(*tasks, **options)
|
59
|
-
|
59
|
+
pipeline << ExecutionGroup.new(
|
60
60
|
tasks.map do |task|
|
61
61
|
next task if task.is_a?(Class) && (task <= Task)
|
62
62
|
|
@@ -87,39 +87,21 @@ module CMDx
|
|
87
87
|
base.extend(ClassMethods)
|
88
88
|
end
|
89
89
|
|
90
|
-
# Executes the workflow by processing
|
91
|
-
#
|
90
|
+
# Executes the workflow by processing all tasks in the pipeline.
|
91
|
+
# This method delegates execution to the Pipeline class which handles
|
92
|
+
# the processing of tasks with proper error handling and context management.
|
92
93
|
#
|
93
|
-
# @return [void]
|
94
|
-
#
|
95
|
-
# @raise [CMDx::Fault] If a breakpoint is encountered during execution
|
96
|
-
#
|
97
|
-
# @example
|
98
|
-
# workflow = MyWorkflow.new
|
99
|
-
# workflow.work # Executes all tasks in the workflow
|
100
94
|
# @example
|
101
|
-
# class
|
95
|
+
# class MyWorkflow
|
102
96
|
# include CMDx::Workflow
|
103
|
-
# task
|
104
|
-
# task
|
105
|
-
# task NotifyCompletionTask
|
97
|
+
# task ValidateTask
|
98
|
+
# task ProcessTask
|
106
99
|
# end
|
107
|
-
#
|
108
|
-
# workflow
|
100
|
+
#
|
101
|
+
# workflow = MyWorkflow.new
|
102
|
+
# result = workflow.work
|
109
103
|
def work
|
110
|
-
self
|
111
|
-
next unless Utils::Condition.evaluate(self, group.options, self)
|
112
|
-
|
113
|
-
breakpoints = group.options[:breakpoints] || self.class.settings[:workflow_breakpoints]
|
114
|
-
breakpoints = Array(breakpoints).map(&:to_s).uniq
|
115
|
-
|
116
|
-
group.tasks.each do |task|
|
117
|
-
task_result = task.execute(context)
|
118
|
-
next unless breakpoints.include?(task_result.status)
|
119
|
-
|
120
|
-
throw!(task_result)
|
121
|
-
end
|
122
|
-
end
|
104
|
+
Pipeline.execute(self)
|
123
105
|
end
|
124
106
|
|
125
107
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cmdx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Juan Gomez
|
@@ -163,9 +163,7 @@ dependencies:
|
|
163
163
|
- - ">="
|
164
164
|
- !ruby/object:Gem::Version
|
165
165
|
version: '0'
|
166
|
-
description:
|
167
|
-
validation, coercion, callbacks, and workflow orchestration for building maintainable
|
168
|
-
business processes.
|
166
|
+
description: CMDx is a framework for building maintainable business processes.
|
169
167
|
email:
|
170
168
|
- drexed@users.noreply.github.com
|
171
169
|
executables: []
|
@@ -237,6 +235,7 @@ files:
|
|
237
235
|
- lib/cmdx/deprecator.rb
|
238
236
|
- lib/cmdx/errors.rb
|
239
237
|
- lib/cmdx/exceptions.rb
|
238
|
+
- lib/cmdx/executor.rb
|
240
239
|
- lib/cmdx/faults.rb
|
241
240
|
- lib/cmdx/freezer.rb
|
242
241
|
- lib/cmdx/identifier.rb
|
@@ -250,6 +249,7 @@ files:
|
|
250
249
|
- lib/cmdx/middlewares/correlate.rb
|
251
250
|
- lib/cmdx/middlewares/runtime.rb
|
252
251
|
- lib/cmdx/middlewares/timeout.rb
|
252
|
+
- lib/cmdx/pipeline.rb
|
253
253
|
- lib/cmdx/railtie.rb
|
254
254
|
- lib/cmdx/result.rb
|
255
255
|
- lib/cmdx/task.rb
|
@@ -264,7 +264,6 @@ files:
|
|
264
264
|
- lib/cmdx/validators/numeric.rb
|
265
265
|
- lib/cmdx/validators/presence.rb
|
266
266
|
- lib/cmdx/version.rb
|
267
|
-
- lib/cmdx/worker.rb
|
268
267
|
- lib/cmdx/workflow.rb
|
269
268
|
- lib/generators/cmdx/install_generator.rb
|
270
269
|
- lib/generators/cmdx/task_generator.rb
|