cmdx 1.0.1 → 1.1.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 +4 -4
- data/.cursor/prompts/docs.md +9 -0
- data/.cursor/prompts/rspec.md +21 -0
- data/.cursor/prompts/yardoc.md +13 -0
- data/.rubocop.yml +2 -0
- data/CHANGELOG.md +29 -3
- data/README.md +2 -1
- data/docs/ai_prompts.md +269 -195
- data/docs/basics/call.md +126 -60
- data/docs/basics/chain.md +190 -160
- data/docs/basics/context.md +242 -154
- data/docs/basics/setup.md +302 -32
- data/docs/callbacks.md +382 -119
- data/docs/configuration.md +211 -49
- data/docs/deprecation.md +245 -0
- data/docs/getting_started.md +161 -39
- data/docs/internationalization.md +590 -70
- data/docs/interruptions/exceptions.md +135 -118
- data/docs/interruptions/faults.md +152 -127
- data/docs/interruptions/halt.md +134 -80
- data/docs/logging.md +183 -120
- data/docs/middlewares.md +165 -392
- data/docs/outcomes/result.md +140 -112
- data/docs/outcomes/states.md +134 -99
- data/docs/outcomes/statuses.md +204 -146
- data/docs/parameters/coercions.md +251 -289
- data/docs/parameters/defaults.md +224 -169
- data/docs/parameters/definitions.md +289 -141
- data/docs/parameters/namespacing.md +250 -161
- data/docs/parameters/validations.md +247 -159
- data/docs/testing.md +196 -203
- data/docs/workflows.md +146 -101
- data/lib/cmdx/.DS_Store +0 -0
- data/lib/cmdx/callback.rb +39 -55
- data/lib/cmdx/callback_registry.rb +80 -73
- data/lib/cmdx/chain.rb +65 -122
- data/lib/cmdx/chain_inspector.rb +23 -116
- data/lib/cmdx/chain_serializer.rb +34 -146
- data/lib/cmdx/coercion.rb +57 -0
- data/lib/cmdx/coercion_registry.rb +113 -0
- data/lib/cmdx/coercions/array.rb +18 -36
- data/lib/cmdx/coercions/big_decimal.rb +21 -33
- data/lib/cmdx/coercions/boolean.rb +21 -40
- data/lib/cmdx/coercions/complex.rb +18 -31
- data/lib/cmdx/coercions/date.rb +20 -39
- data/lib/cmdx/coercions/date_time.rb +22 -39
- data/lib/cmdx/coercions/float.rb +19 -32
- data/lib/cmdx/coercions/hash.rb +22 -41
- data/lib/cmdx/coercions/integer.rb +20 -33
- data/lib/cmdx/coercions/rational.rb +20 -32
- data/lib/cmdx/coercions/string.rb +23 -31
- data/lib/cmdx/coercions/time.rb +24 -40
- data/lib/cmdx/coercions/virtual.rb +14 -31
- data/lib/cmdx/configuration.rb +101 -162
- data/lib/cmdx/context.rb +34 -166
- data/lib/cmdx/core_ext/hash.rb +42 -67
- data/lib/cmdx/core_ext/module.rb +35 -79
- data/lib/cmdx/core_ext/object.rb +63 -98
- data/lib/cmdx/correlator.rb +59 -154
- data/lib/cmdx/error.rb +37 -202
- data/lib/cmdx/errors.rb +153 -216
- data/lib/cmdx/fault.rb +68 -150
- data/lib/cmdx/faults.rb +26 -137
- data/lib/cmdx/immutator.rb +22 -110
- data/lib/cmdx/lazy_struct.rb +110 -186
- data/lib/cmdx/log_formatters/json.rb +14 -40
- data/lib/cmdx/log_formatters/key_value.rb +14 -40
- data/lib/cmdx/log_formatters/line.rb +14 -48
- data/lib/cmdx/log_formatters/logstash.rb +14 -57
- data/lib/cmdx/log_formatters/pretty_json.rb +14 -50
- data/lib/cmdx/log_formatters/pretty_key_value.rb +13 -46
- data/lib/cmdx/log_formatters/pretty_line.rb +16 -54
- data/lib/cmdx/log_formatters/raw.rb +19 -49
- data/lib/cmdx/logger.rb +22 -79
- data/lib/cmdx/logger_ansi.rb +31 -72
- data/lib/cmdx/logger_serializer.rb +74 -103
- data/lib/cmdx/middleware.rb +56 -60
- data/lib/cmdx/middleware_registry.rb +82 -77
- data/lib/cmdx/middlewares/correlate.rb +41 -226
- data/lib/cmdx/middlewares/timeout.rb +46 -185
- data/lib/cmdx/parameter.rb +167 -183
- data/lib/cmdx/parameter_evaluator.rb +231 -0
- data/lib/cmdx/parameter_inspector.rb +37 -55
- data/lib/cmdx/parameter_registry.rb +65 -84
- data/lib/cmdx/parameter_serializer.rb +32 -76
- data/lib/cmdx/railtie.rb +24 -107
- data/lib/cmdx/result.rb +254 -259
- data/lib/cmdx/result_ansi.rb +28 -80
- data/lib/cmdx/result_inspector.rb +34 -70
- data/lib/cmdx/result_logger.rb +23 -77
- data/lib/cmdx/result_serializer.rb +59 -125
- data/lib/cmdx/rspec/matchers.rb +28 -0
- data/lib/cmdx/rspec/result_matchers/be_executed.rb +42 -0
- data/lib/cmdx/rspec/result_matchers/be_failed_task.rb +94 -0
- data/lib/cmdx/rspec/result_matchers/be_skipped_task.rb +94 -0
- data/lib/cmdx/rspec/result_matchers/be_state_matchers.rb +59 -0
- data/lib/cmdx/rspec/result_matchers/be_status_matchers.rb +57 -0
- data/lib/cmdx/rspec/result_matchers/be_successful_task.rb +87 -0
- data/lib/cmdx/rspec/result_matchers/have_bad_outcome.rb +51 -0
- data/lib/cmdx/rspec/result_matchers/have_caused_failure.rb +58 -0
- data/lib/cmdx/rspec/result_matchers/have_chain_index.rb +59 -0
- data/lib/cmdx/rspec/result_matchers/have_context.rb +86 -0
- data/lib/cmdx/rspec/result_matchers/have_empty_metadata.rb +54 -0
- data/lib/cmdx/rspec/result_matchers/have_good_outcome.rb +52 -0
- data/lib/cmdx/rspec/result_matchers/have_metadata.rb +114 -0
- data/lib/cmdx/rspec/result_matchers/have_preserved_context.rb +66 -0
- data/lib/cmdx/rspec/result_matchers/have_received_thrown_failure.rb +64 -0
- data/lib/cmdx/rspec/result_matchers/have_runtime.rb +78 -0
- data/lib/cmdx/rspec/result_matchers/have_thrown_failure.rb +76 -0
- data/lib/cmdx/rspec/task_matchers/be_well_formed_task.rb +62 -0
- data/lib/cmdx/rspec/task_matchers/have_callback.rb +85 -0
- data/lib/cmdx/rspec/task_matchers/have_cmd_setting.rb +68 -0
- data/lib/cmdx/rspec/task_matchers/have_executed_callbacks.rb +92 -0
- data/lib/cmdx/rspec/task_matchers/have_middleware.rb +46 -0
- data/lib/cmdx/rspec/task_matchers/have_parameter.rb +181 -0
- data/lib/cmdx/task.rb +336 -427
- data/lib/cmdx/task_deprecator.rb +52 -0
- data/lib/cmdx/task_processor.rb +246 -0
- data/lib/cmdx/task_serializer.rb +34 -69
- data/lib/cmdx/utils/ansi_color.rb +13 -89
- data/lib/cmdx/utils/log_timestamp.rb +13 -42
- data/lib/cmdx/utils/monotonic_runtime.rb +11 -63
- data/lib/cmdx/utils/name_affix.rb +21 -71
- data/lib/cmdx/validator.rb +57 -0
- data/lib/cmdx/validator_registry.rb +108 -0
- data/lib/cmdx/validators/exclusion.rb +55 -94
- data/lib/cmdx/validators/format.rb +31 -85
- data/lib/cmdx/validators/inclusion.rb +65 -110
- data/lib/cmdx/validators/length.rb +117 -133
- data/lib/cmdx/validators/numeric.rb +123 -130
- data/lib/cmdx/validators/presence.rb +38 -79
- data/lib/cmdx/version.rb +1 -7
- data/lib/cmdx/workflow.rb +58 -330
- data/lib/cmdx.rb +1 -1
- data/lib/generators/cmdx/install_generator.rb +14 -31
- data/lib/generators/cmdx/task_generator.rb +39 -55
- data/lib/generators/cmdx/templates/install.rb +24 -6
- data/lib/generators/cmdx/workflow_generator.rb +41 -66
- data/lib/locales/ar.yml +0 -1
- data/lib/locales/cs.yml +0 -1
- data/lib/locales/da.yml +0 -1
- data/lib/locales/de.yml +0 -1
- data/lib/locales/el.yml +0 -1
- data/lib/locales/en.yml +0 -1
- data/lib/locales/es.yml +0 -1
- data/lib/locales/fi.yml +0 -1
- data/lib/locales/fr.yml +0 -1
- data/lib/locales/he.yml +0 -1
- data/lib/locales/hi.yml +0 -1
- data/lib/locales/it.yml +0 -1
- data/lib/locales/ja.yml +0 -1
- data/lib/locales/ko.yml +0 -1
- data/lib/locales/nl.yml +0 -1
- data/lib/locales/no.yml +0 -1
- data/lib/locales/pl.yml +0 -1
- data/lib/locales/pt.yml +0 -1
- data/lib/locales/ru.yml +0 -1
- data/lib/locales/sv.yml +0 -1
- data/lib/locales/th.yml +0 -1
- data/lib/locales/tr.yml +0 -1
- data/lib/locales/vi.yml +0 -1
- data/lib/locales/zh.yml +0 -1
- metadata +36 -8
- data/lib/cmdx/parameter_validator.rb +0 -81
- data/lib/cmdx/parameter_value.rb +0 -244
- data/lib/cmdx/parameters_inspector.rb +0 -72
- data/lib/cmdx/parameters_serializer.rb +0 -115
- data/lib/cmdx/rspec/result_matchers.rb +0 -917
- data/lib/cmdx/rspec/task_matchers.rb +0 -570
- data/lib/cmdx/validators/custom.rb +0 -102
@@ -1,239 +1,264 @@
|
|
1
1
|
# Interruptions - Faults
|
2
2
|
|
3
|
-
Faults are
|
4
|
-
`skip!` and `fail!` methods. When tasks are executed with the bang `call!` method,
|
5
|
-
fault exceptions matching the task's interruption status are raised, enabling
|
6
|
-
sophisticated exception handling and control flow patterns.
|
3
|
+
Faults are exception mechanisms that halt task execution via `skip!` and `fail!` methods. When tasks execute with the `call!` method, fault exceptions matching the task's interruption status are raised, enabling sophisticated exception handling and control flow patterns.
|
7
4
|
|
8
5
|
## Table of Contents
|
9
6
|
|
10
7
|
- [TLDR](#tldr)
|
11
8
|
- [Fault Types](#fault-types)
|
12
|
-
- [
|
9
|
+
- [Exception Handling](#exception-handling)
|
13
10
|
- [Fault Context Access](#fault-context-access)
|
14
|
-
- [Advanced
|
15
|
-
- [Fault Propagation
|
16
|
-
- [
|
17
|
-
- [
|
11
|
+
- [Advanced Matching](#advanced-matching)
|
12
|
+
- [Fault Propagation](#fault-propagation)
|
13
|
+
- [Chain Analysis](#chain-analysis)
|
14
|
+
- [Configuration](#configuration)
|
18
15
|
|
19
16
|
## TLDR
|
20
17
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
18
|
+
```ruby
|
19
|
+
# Basic exception handling
|
20
|
+
begin
|
21
|
+
PaymentProcessor.call!(amount: 100)
|
22
|
+
rescue CMDx::Skipped => e
|
23
|
+
handle_skipped_payment(e.result.metadata[:reason])
|
24
|
+
rescue CMDx::Failed => e
|
25
|
+
handle_failed_payment(e.result.metadata[:error])
|
26
|
+
rescue CMDx::Fault => e
|
27
|
+
handle_any_interruption(e)
|
28
|
+
end
|
26
29
|
|
27
|
-
|
30
|
+
# Advanced matching
|
31
|
+
rescue CMDx::Failed.for?(PaymentProcessor, CardValidator) => e
|
32
|
+
rescue CMDx::Fault.matches? { |f| f.context.amount > 1000 } => e
|
28
33
|
|
29
|
-
|
34
|
+
# Fault propagation
|
35
|
+
throw!(validation_result) if validation_result.failed?
|
36
|
+
```
|
30
37
|
|
31
|
-
|
32
|
-
- **`CMDx::Failed`** - Raised when a task fails via `fail!`
|
38
|
+
## Fault Types
|
33
39
|
|
34
|
-
|
35
|
-
|
40
|
+
| Type | Triggered By | Use Case |
|
41
|
+
|------|--------------|----------|
|
42
|
+
| `CMDx::Skipped` | `skip!` method | Optional processing, early returns |
|
43
|
+
| `CMDx::Failed` | `fail!` method | Validation errors, processing failures |
|
44
|
+
| `CMDx::Fault` | Base class | Catch-all for any interruption |
|
36
45
|
|
37
46
|
> [!NOTE]
|
38
|
-
> All fault exceptions
|
47
|
+
> All fault exceptions inherit from `CMDx::Fault` and provide access to the complete task execution context including result, task, context, and chain information.
|
39
48
|
|
40
|
-
##
|
49
|
+
## Exception Handling
|
41
50
|
|
42
|
-
|
51
|
+
### Basic Rescue Patterns
|
43
52
|
|
44
53
|
```ruby
|
45
54
|
begin
|
46
|
-
|
55
|
+
ProcessOrderTask.call!(order_id: 123)
|
47
56
|
rescue CMDx::Skipped => e
|
48
|
-
|
49
|
-
|
50
|
-
e.result.metadata[:reason] #=> "Order already processed"
|
57
|
+
logger.info "Order processing skipped: #{e.message}"
|
58
|
+
schedule_retry(e.context.order_id)
|
51
59
|
rescue CMDx::Failed => e
|
52
|
-
|
53
|
-
|
54
|
-
e.result.metadata[:error_code] #=> "PAYMENT_DECLINED"
|
60
|
+
logger.error "Order processing failed: #{e.message}"
|
61
|
+
notify_customer(e.context.customer_email, e.result.metadata[:error])
|
55
62
|
rescue CMDx::Fault => e
|
56
|
-
|
57
|
-
|
63
|
+
logger.warn "Order processing interrupted: #{e.message}"
|
64
|
+
rollback_transaction
|
65
|
+
end
|
66
|
+
```
|
67
|
+
|
68
|
+
### Error-Specific Handling
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
begin
|
72
|
+
PaymentProcessor.call!(card_token: token, amount: amount)
|
73
|
+
rescue CMDx::Failed => e
|
74
|
+
case e.result.metadata[:error_code]
|
75
|
+
when "INSUFFICIENT_FUNDS"
|
76
|
+
suggest_different_payment_method
|
77
|
+
when "CARD_DECLINED"
|
78
|
+
request_card_verification
|
79
|
+
when "NETWORK_ERROR"
|
80
|
+
retry_payment_later
|
81
|
+
else
|
82
|
+
escalate_to_support(e)
|
83
|
+
end
|
58
84
|
end
|
59
85
|
```
|
60
86
|
|
61
87
|
## Fault Context Access
|
62
88
|
|
63
|
-
Faults provide comprehensive access to
|
89
|
+
Faults provide comprehensive access to execution context:
|
64
90
|
|
65
91
|
```ruby
|
66
92
|
begin
|
67
|
-
|
93
|
+
UserRegistration.call!(email: email, password: password)
|
68
94
|
rescue CMDx::Fault => e
|
69
95
|
# Result information
|
70
96
|
e.result.status #=> "failed" or "skipped"
|
71
|
-
e.result.metadata[:reason] #=> "
|
97
|
+
e.result.metadata[:reason] #=> "Email already exists"
|
72
98
|
e.result.runtime #=> 0.05
|
73
99
|
|
74
100
|
# Task information
|
75
|
-
e.task.class.name #=> "
|
101
|
+
e.task.class.name #=> "UserRegistration"
|
76
102
|
e.task.id #=> "abc123..."
|
77
103
|
|
78
104
|
# Context data
|
79
|
-
e.context.
|
80
|
-
e.context.
|
105
|
+
e.context.email #=> "user@example.com"
|
106
|
+
e.context.password #=> "[FILTERED]"
|
81
107
|
|
82
|
-
# Chain information
|
83
|
-
e.chain
|
84
|
-
e.chain
|
108
|
+
# Chain information (for workflows)
|
109
|
+
e.chain&.id #=> "def456..."
|
110
|
+
e.chain&.results&.size #=> 3
|
85
111
|
end
|
86
112
|
```
|
87
113
|
|
88
|
-
## Advanced
|
114
|
+
## Advanced Matching
|
89
115
|
|
90
|
-
### Task-Specific Matching
|
116
|
+
### Task-Specific Matching
|
91
117
|
|
92
|
-
|
118
|
+
> [!TIP]
|
119
|
+
> Use `for?` to handle faults only from specific task classes, enabling targeted exception handling in complex workflows.
|
93
120
|
|
94
121
|
```ruby
|
95
122
|
begin
|
96
|
-
|
97
|
-
rescue CMDx::
|
98
|
-
# Handle
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
logger.error "Payment processing failed: #{e.message}"
|
104
|
-
retry_with_backup_payment_method(e.context)
|
123
|
+
PaymentWorkflow.call!(payment_data: data)
|
124
|
+
rescue CMDx::Failed.for?(CardValidator, PaymentProcessor) => e
|
125
|
+
# Handle only payment-related failures
|
126
|
+
retry_with_backup_method(e.context)
|
127
|
+
rescue CMDx::Skipped.for?(FraudCheck, RiskAssessment) => e
|
128
|
+
# Handle security-related skips
|
129
|
+
flag_for_manual_review(e.context.transaction_id)
|
105
130
|
end
|
106
131
|
```
|
107
132
|
|
108
|
-
### Custom
|
109
|
-
|
110
|
-
Use the `matches?` method with blocks for sophisticated fault matching:
|
133
|
+
### Custom Logic Matching
|
111
134
|
|
112
135
|
```ruby
|
113
136
|
begin
|
114
|
-
|
115
|
-
rescue CMDx::Fault.matches? { |f| f.result.metadata[:error_code] == "PAYMENT_DECLINED" } => e
|
116
|
-
# Handle specific payment errors
|
117
|
-
retry_with_different_payment_method(e.context)
|
137
|
+
OrderProcessor.call!(order: order_data)
|
118
138
|
rescue CMDx::Fault.matches? { |f| f.context.order_value > 1000 } => e
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
139
|
+
escalate_high_value_failure(e)
|
140
|
+
rescue CMDx::Failed.matches? { |f| f.result.metadata[:retry_count] > 3 } => e
|
141
|
+
abandon_processing(e)
|
142
|
+
rescue CMDx::Fault.matches? { |f| f.result.metadata[:error_type] == "timeout" } => e
|
143
|
+
increase_timeout_and_retry(e)
|
124
144
|
end
|
125
145
|
```
|
126
146
|
|
127
|
-
|
128
|
-
> Use `for?` and `matches?` methods for advanced exception matching. The `for?` method is ideal for task-specific handling, while `matches?` enables custom logic-based fault filtering.
|
129
|
-
|
130
|
-
## Fault Propagation (`throw!`)
|
147
|
+
## Fault Propagation
|
131
148
|
|
132
|
-
|
133
|
-
|
149
|
+
> [!IMPORTANT]
|
150
|
+
> Use `throw!` to propagate failures while preserving fault context and maintaining the error chain for debugging.
|
134
151
|
|
135
152
|
### Basic Propagation
|
136
153
|
|
137
154
|
```ruby
|
138
|
-
class
|
139
|
-
|
155
|
+
class OrderProcessor < CMDx::Task
|
140
156
|
def call
|
141
|
-
#
|
142
|
-
validation_result =
|
157
|
+
# Validate order data
|
158
|
+
validation_result = OrderValidator.call(context)
|
143
159
|
throw!(validation_result) if validation_result.failed?
|
144
160
|
|
145
|
-
|
146
|
-
|
161
|
+
# Process payment
|
162
|
+
payment_result = PaymentProcessor.call(context)
|
163
|
+
throw!(payment_result) if payment_result.failed?
|
147
164
|
|
148
|
-
# Continue
|
149
|
-
|
165
|
+
# Continue processing
|
166
|
+
complete_order
|
150
167
|
end
|
151
|
-
|
152
168
|
end
|
153
169
|
```
|
154
170
|
|
155
|
-
### Propagation with
|
171
|
+
### Propagation with Context
|
156
172
|
|
157
173
|
```ruby
|
158
|
-
class
|
159
|
-
|
174
|
+
class WorkflowProcessor < CMDx::Task
|
160
175
|
def call
|
161
|
-
|
162
|
-
|
163
|
-
if
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
can_retry: true
|
176
|
+
step_result = DataValidation.call(context)
|
177
|
+
|
178
|
+
if step_result.failed?
|
179
|
+
throw!(step_result, {
|
180
|
+
workflow_stage: "validation",
|
181
|
+
can_retry: true,
|
182
|
+
next_step: "data_cleanup"
|
169
183
|
})
|
170
184
|
end
|
171
185
|
|
172
186
|
continue_workflow
|
173
187
|
end
|
174
|
-
|
175
188
|
end
|
176
189
|
```
|
177
190
|
|
178
|
-
|
179
|
-
> Use `throw!` to propagate failures while preserving the original fault context. This maintains the fault chain for debugging and provides better error traceability.
|
180
|
-
|
181
|
-
## Fault Chain Analysis
|
191
|
+
## Chain Analysis
|
182
192
|
|
183
|
-
|
193
|
+
> [!NOTE]
|
194
|
+
> Results provide methods to analyze fault propagation and identify original failure sources in complex execution chains.
|
184
195
|
|
185
196
|
```ruby
|
186
|
-
result =
|
197
|
+
result = PaymentWorkflow.call(invalid_data)
|
187
198
|
|
188
199
|
if result.failed?
|
189
|
-
#
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
200
|
+
# Trace the original failure
|
201
|
+
original = result.caused_failure
|
202
|
+
if original
|
203
|
+
puts "Original failure: #{original.task.class.name}"
|
204
|
+
puts "Reason: #{original.metadata[:reason]}"
|
205
|
+
end
|
206
|
+
|
207
|
+
# Find what propagated the failure
|
208
|
+
thrower = result.threw_failure
|
209
|
+
puts "Propagated by: #{thrower.task.class.name}" if thrower
|
210
|
+
|
211
|
+
# Analyze failure type
|
212
|
+
case
|
213
|
+
when result.caused_failure?
|
214
|
+
puts "This task was the original source"
|
215
|
+
when result.threw_failure?
|
216
|
+
puts "This task propagated a failure"
|
217
|
+
when result.thrown_failure?
|
218
|
+
puts "This task failed due to propagation"
|
205
219
|
end
|
206
220
|
end
|
207
221
|
```
|
208
222
|
|
209
|
-
##
|
223
|
+
## Configuration
|
210
224
|
|
211
|
-
|
225
|
+
### Task Halt Settings
|
226
|
+
|
227
|
+
Control which statuses raise exceptions using `task_halt`:
|
212
228
|
|
213
229
|
```ruby
|
214
|
-
class
|
215
|
-
# Only
|
216
|
-
|
230
|
+
class DataProcessor < CMDx::Task
|
231
|
+
# Only failures raise exceptions
|
232
|
+
cmd_settings!(task_halt: [CMDx::Result::FAILED])
|
217
233
|
|
218
234
|
def call
|
219
|
-
skip!(reason: "
|
220
|
-
#
|
235
|
+
skip!(reason: "No data to process") if data.empty?
|
236
|
+
# Skip will NOT raise exception on call!
|
221
237
|
end
|
222
238
|
end
|
223
239
|
|
224
|
-
class
|
225
|
-
# Both
|
226
|
-
|
240
|
+
class CriticalValidator < CMDx::Task
|
241
|
+
# Both failures and skips raise exceptions
|
242
|
+
cmd_settings!(task_halt: [CMDx::Result::FAILED, CMDx::Result::SKIPPED])
|
227
243
|
|
228
244
|
def call
|
229
|
-
skip!(reason: "Validation
|
230
|
-
#
|
245
|
+
skip!(reason: "Validation bypassed") if bypass_mode?
|
246
|
+
# Skip WILL raise exception on call!
|
231
247
|
end
|
232
248
|
end
|
233
249
|
```
|
234
250
|
|
235
251
|
> [!WARNING]
|
236
|
-
> Task halt configuration only affects the `call!` method. The `call` method always captures
|
252
|
+
> Task halt configuration only affects the `call!` method. The `call` method always captures exceptions and converts them to result objects regardless of halt settings.
|
253
|
+
|
254
|
+
### Global Configuration
|
255
|
+
|
256
|
+
```ruby
|
257
|
+
# Configure default halt behavior
|
258
|
+
CMDx.configure do |config|
|
259
|
+
config.task_halt = [CMDx::Result::FAILED] # Default: only failures halt
|
260
|
+
end
|
261
|
+
```
|
237
262
|
|
238
263
|
---
|
239
264
|
|