cmdx 1.5.2 → 1.6.1

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: 14a2616a171c3c514fbc553369936eac48fe2fd3d8e406cc4780ee39a483637f
4
- data.tar.gz: 28d973a4973c4f2dc5e3acf1c1a09d4a0e0fbe158bc2f3553a5722acb9490051
3
+ metadata.gz: c054b422d416bb8f3605c0c75961c2dc65fc3ba7aba3125fcd66f1107276dc8a
4
+ data.tar.gz: 05b168249fcf03d62cee5a68a98b30fb038f5da90bea4044809a6e52ee1f2ca2
5
5
  SHA512:
6
- metadata.gz: 363225923cd389ddca29f5580321ef3fb3efe863b08480a31b505f67ca08db260695e752631f0b58912421679bc43b52bd679c6e3a0441a8d54628f7b09d855c
7
- data.tar.gz: 7d479a75b0e048e9eb7385ce31b7f3bc10512856ba9fe95b34bde5b4a833822787a087d0420a6020830fc322846d72e80604ff3706d25795cc486707d1c31726
6
+ metadata.gz: fe3426a7c2d2a8839583695c9682fb3499bc6e2707349a5e872b293a7100442a7f328212783e083c68f3995379fd8db0cf44b56156506b71e14abf59f3c0d3ec
7
+ data.tar.gz: d29594887e332518500b3af872f987540fc41ff8293a13252bf665b0a2669da38944875b91caab1916d004de6e7b616ef17016de55b667ad80fcff301a153dc7
data/CHANGELOG.md CHANGED
@@ -6,10 +6,23 @@ 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.1] - 2025-08-23
10
+
11
+ ### Changes
12
+ - Log task results before freezing
13
+ - Rename `execute_tasks_sequentially` to `execute_tasks_in_sequence`
14
+
15
+ ## [1.6.0] - 2025-08-22
16
+
17
+ ### Changes
18
+ - Rename `Worker` class to `Executor`
19
+ - Move workflow `work` logic into `Pipeline`
20
+ - Add workflow task `:breakpoints`
21
+
9
22
  ## [1.5.2] - 2025-08-22
10
23
 
11
24
  ### Changes
12
- - Rename the workflow `execution_groups` attribute to `pipeline`
25
+ - Rename workflow `execution_groups` attribute to `pipeline`
13
26
 
14
27
  ## [1.5.1] - 2025-08-21
15
28
 
data/LLM.md CHANGED
@@ -2794,8 +2794,7 @@ CMDx provides comprehensive internationalization support for all error messages,
2794
2794
 
2795
2795
  ## Localization
2796
2796
 
2797
- > [!NOTE]
2798
- > 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.
2799
2798
 
2800
2799
  ```ruby
2801
2800
  class ProcessQuote < CMDx::Task
@@ -2812,6 +2811,9 @@ I18n.with_locale(:fr) do
2812
2811
  end
2813
2812
  ```
2814
2813
 
2814
+ > [!TIP]
2815
+ > CMDx supports 85+ locales via the [cmdx-i18n](https://github.com/drexed/cmdx-i18n) gem.
2816
+
2815
2817
  ---
2816
2818
 
2817
2819
  url: https://github.com/drexed/cmdx/blob/main/docs/deprecation.md
@@ -2991,6 +2993,9 @@ class OnboardingWorkflow < CMDx::Task
2991
2993
  end
2992
2994
  ```
2993
2995
 
2996
+ > [!TIP]
2997
+ > Execute tasks in parallel via the [cmdx-parallel](https://github.com/drexed/cmdx-parallel) gem.
2998
+
2994
2999
  ### Group
2995
3000
 
2996
3001
  Group related tasks for better organization and shared configuration:
data/README.md CHANGED
@@ -123,11 +123,11 @@ end
123
123
  ## Ecosystem
124
124
 
125
125
  - [cmdx-i18n](https://github.com/drexed/cmdx-i18n) - 85+ translations
126
+ - [cmdx-parallel](https://github.com/drexed/cmdx-parallel) - Parallel workflow tasks
126
127
 
127
128
  The following gems are currently under development:
128
129
 
129
130
  - `cmdx-testing` - RSpec and Minitest matchers
130
- - `cmdx-parallel` - Parallel workflow task execution
131
131
 
132
132
  ## Development
133
133
 
@@ -8,8 +8,7 @@ CMDx provides comprehensive internationalization support for all error messages,
8
8
 
9
9
  ## Localization
10
10
 
11
- > [!NOTE]
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
@@ -33,6 +33,9 @@ class OnboardingWorkflow < CMDx::Task
33
33
  end
34
34
  ```
35
35
 
36
+ > [!TIP]
37
+ > Execute tasks in parallel via the [cmdx-parallel](https://github.com/drexed/cmdx-parallel) gem.
38
+
36
39
  ### Group
37
40
 
38
41
  Group related tasks for better organization and shared configuration:
@@ -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 Worker class is responsible for orchestrating task execution, including
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 Worker
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::Worker] A new worker instance
15
+ # @return [CMDx::Executor] A new executor instance
16
16
  #
17
17
  # @example
18
- # worker = CMDx::Worker.new(my_task)
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::Worker.execute(my_task)
34
- # CMDx::Worker.execute(my_task, raise: true)
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
- # worker = CMDx::Worker.new(my_task)
46
- # result = worker.execute
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
- # worker = CMDx::Worker.new(my_task)
73
- # result = worker.execute!
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!
@@ -165,13 +165,13 @@ module CMDx
165
165
 
166
166
  # Finalizes execution by freezing the task and logging results.
167
167
  def finalize_execution!
168
- Freezer.immute(task)
169
-
170
168
  task.logger.tap do |logger|
171
169
  logger.with_level(:info) do
172
170
  logger.info { task.result.to_h }
173
171
  end
174
172
  end
173
+
174
+ Freezer.immute(task)
175
175
  end
176
176
 
177
177
  end
@@ -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_in_sequence(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_in_sequence(group, ["failed", "skipped"])
89
+ def execute_tasks_in_sequence(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
- Worker.execute(self, raise:)
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
@@ -2,6 +2,6 @@
2
2
 
3
3
  module CMDx
4
4
 
5
- VERSION = "1.5.2"
5
+ VERSION = "1.6.1"
6
6
 
7
7
  end
data/lib/cmdx/workflow.rb CHANGED
@@ -87,39 +87,21 @@ module CMDx
87
87
  base.extend(ClassMethods)
88
88
  end
89
89
 
90
- # Executes the workflow by processing each execution group sequentially.
91
- # Tasks within each group are executed based on conditional logic and breakpoint handling.
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 DataProcessingWorkflow
95
+ # class MyWorkflow
102
96
  # include CMDx::Workflow
103
- # task ValidateDataTask, breakpoints: [:failure]
104
- # task ProcessDataTask, breakpoints: [:halt]
105
- # task NotifyCompletionTask
97
+ # task ValidateTask
98
+ # task ProcessTask
106
99
  # end
107
- # workflow = DataProcessingWorkflow.new
108
- # workflow.work # Stops on first breakpoint encountered
100
+ #
101
+ # workflow = MyWorkflow.new
102
+ # result = workflow.work
109
103
  def work
110
- self.class.pipeline.each do |group|
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.5.2
4
+ version: 1.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juan Gomez
@@ -235,6 +235,7 @@ files:
235
235
  - lib/cmdx/deprecator.rb
236
236
  - lib/cmdx/errors.rb
237
237
  - lib/cmdx/exceptions.rb
238
+ - lib/cmdx/executor.rb
238
239
  - lib/cmdx/faults.rb
239
240
  - lib/cmdx/freezer.rb
240
241
  - lib/cmdx/identifier.rb
@@ -248,6 +249,7 @@ files:
248
249
  - lib/cmdx/middlewares/correlate.rb
249
250
  - lib/cmdx/middlewares/runtime.rb
250
251
  - lib/cmdx/middlewares/timeout.rb
252
+ - lib/cmdx/pipeline.rb
251
253
  - lib/cmdx/railtie.rb
252
254
  - lib/cmdx/result.rb
253
255
  - lib/cmdx/task.rb
@@ -262,7 +264,6 @@ files:
262
264
  - lib/cmdx/validators/numeric.rb
263
265
  - lib/cmdx/validators/presence.rb
264
266
  - lib/cmdx/version.rb
265
- - lib/cmdx/worker.rb
266
267
  - lib/cmdx/workflow.rb
267
268
  - lib/generators/cmdx/install_generator.rb
268
269
  - lib/generators/cmdx/task_generator.rb