cmdx 1.0.0 → 1.1.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/.cursor/prompts/rspec.md +20 -0
- data/.cursor/prompts/yardoc.md +8 -0
- data/.rubocop.yml +5 -0
- data/CHANGELOG.md +101 -49
- data/README.md +2 -1
- data/docs/ai_prompts.md +10 -0
- data/docs/basics/call.md +11 -2
- data/docs/basics/chain.md +10 -1
- data/docs/basics/context.md +9 -0
- data/docs/basics/setup.md +9 -0
- data/docs/callbacks.md +14 -37
- data/docs/configuration.md +68 -27
- data/docs/getting_started.md +11 -0
- data/docs/internationalization.md +148 -0
- data/docs/interruptions/exceptions.md +10 -1
- data/docs/interruptions/faults.md +11 -2
- data/docs/interruptions/halt.md +9 -0
- data/docs/logging.md +14 -4
- data/docs/middlewares.md +53 -43
- data/docs/outcomes/result.md +9 -0
- data/docs/outcomes/states.md +9 -0
- data/docs/outcomes/statuses.md +9 -0
- data/docs/parameters/coercions.md +58 -38
- data/docs/parameters/defaults.md +10 -1
- data/docs/parameters/definitions.md +9 -0
- data/docs/parameters/namespacing.md +9 -0
- data/docs/parameters/validations.md +8 -67
- data/docs/testing.md +22 -13
- data/docs/tips_and_tricks.md +9 -0
- data/docs/workflows.md +14 -4
- data/lib/cmdx/.DS_Store +0 -0
- data/lib/cmdx/callback.rb +36 -56
- data/lib/cmdx/callback_registry.rb +82 -73
- data/lib/cmdx/chain.rb +65 -122
- data/lib/cmdx/chain_inspector.rb +22 -115
- data/lib/cmdx/chain_serializer.rb +17 -148
- data/lib/cmdx/coercion.rb +49 -0
- data/lib/cmdx/coercion_registry.rb +94 -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 +57 -171
- data/lib/cmdx/context.rb +22 -165
- 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 +40 -156
- data/lib/cmdx/error.rb +37 -202
- data/lib/cmdx/errors.rb +165 -202
- data/lib/cmdx/fault.rb +55 -158
- data/lib/cmdx/faults.rb +26 -137
- data/lib/cmdx/immutator.rb +22 -109
- data/lib/cmdx/lazy_struct.rb +103 -187
- 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 +20 -82
- data/lib/cmdx/logger_ansi.rb +18 -75
- data/lib/cmdx/logger_serializer.rb +24 -114
- data/lib/cmdx/middleware.rb +38 -60
- data/lib/cmdx/middleware_registry.rb +81 -77
- data/lib/cmdx/middlewares/correlate.rb +41 -226
- data/lib/cmdx/middlewares/timeout.rb +46 -185
- data/lib/cmdx/parameter.rb +120 -198
- data/lib/cmdx/parameter_evaluator.rb +231 -0
- data/lib/cmdx/parameter_inspector.rb +25 -56
- data/lib/cmdx/parameter_registry.rb +59 -84
- data/lib/cmdx/parameter_serializer.rb +23 -74
- data/lib/cmdx/railtie.rb +24 -107
- data/lib/cmdx/result.rb +254 -260
- data/lib/cmdx/result_ansi.rb +19 -85
- data/lib/cmdx/result_inspector.rb +27 -68
- data/lib/cmdx/result_logger.rb +18 -81
- data/lib/cmdx/result_serializer.rb +28 -132
- 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 +213 -425
- data/lib/cmdx/task_deprecator.rb +55 -0
- data/lib/cmdx/task_processor.rb +245 -0
- data/lib/cmdx/task_serializer.rb +22 -70
- 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 +13 -63
- data/lib/cmdx/utils/name_affix.rb +21 -71
- data/lib/cmdx/validator.rb +48 -0
- data/lib/cmdx/validator_registry.rb +86 -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 +46 -339
- 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 +61 -11
- data/lib/generators/cmdx/workflow_generator.rb +41 -66
- data/lib/locales/ar.yml +35 -0
- data/lib/locales/cs.yml +35 -0
- data/lib/locales/da.yml +35 -0
- data/lib/locales/de.yml +35 -0
- data/lib/locales/el.yml +35 -0
- data/lib/locales/en.yml +19 -20
- data/lib/locales/es.yml +19 -20
- data/lib/locales/fi.yml +35 -0
- data/lib/locales/fr.yml +35 -0
- data/lib/locales/he.yml +35 -0
- data/lib/locales/hi.yml +35 -0
- data/lib/locales/it.yml +35 -0
- data/lib/locales/ja.yml +35 -0
- data/lib/locales/ko.yml +35 -0
- data/lib/locales/nl.yml +35 -0
- data/lib/locales/no.yml +35 -0
- data/lib/locales/pl.yml +35 -0
- data/lib/locales/pt.yml +35 -0
- data/lib/locales/ru.yml +35 -0
- data/lib/locales/sv.yml +35 -0
- data/lib/locales/th.yml +35 -0
- data/lib/locales/tr.yml +35 -0
- data/lib/locales/vi.yml +35 -0
- data/lib/locales/zh.yml +35 -0
- metadata +57 -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
data/docs/configuration.md
CHANGED
@@ -4,11 +4,14 @@ CMDx provides a flexible configuration system that allows customization at both
|
|
4
4
|
|
5
5
|
## Table of Contents
|
6
6
|
|
7
|
+
- [TLDR](#tldr)
|
7
8
|
- [Configuration Hierarchy](#configuration-hierarchy)
|
8
9
|
- [Global Configuration](#global-configuration)
|
9
10
|
- [Configuration Options](#configuration-options)
|
10
11
|
- [Global Middlewares](#global-middlewares)
|
11
12
|
- [Global Callbacks](#global-callbacks)
|
13
|
+
- [Global Coercions](#global-coercions)
|
14
|
+
- [Global Validators](#global-validators)
|
12
15
|
- [Task Settings](#task-settings)
|
13
16
|
- [Available Task Settings](#available-task-settings)
|
14
17
|
- [Workflow Configuration](#workflow-configuration)
|
@@ -16,12 +19,21 @@ CMDx provides a flexible configuration system that allows customization at both
|
|
16
19
|
- [Accessing Configuration](#accessing-configuration)
|
17
20
|
- [Resetting Configuration](#resetting-configuration)
|
18
21
|
|
22
|
+
## TLDR
|
23
|
+
|
24
|
+
- **Hierarchy** - Global → Task Settings → Runtime (each level overrides previous)
|
25
|
+
- **Global config** - Framework-wide defaults via `CMDx.configure`
|
26
|
+
- **Task settings** - Class-level overrides using `cmd_settings!`
|
27
|
+
- **Key options** - `task_halt`, `workflow_halt`, `logger`, `middlewares`, `callbacks`
|
28
|
+
- **Generator** - Use `rails g cmdx:install` to create configuration file
|
29
|
+
- **Inheritance** - Settings are inherited from parent classes
|
30
|
+
|
19
31
|
## Configuration Hierarchy
|
20
32
|
|
21
33
|
CMDx follows a three-tier configuration hierarchy:
|
22
34
|
|
23
35
|
1. **Global Configuration**: Framework-wide defaults
|
24
|
-
2. **Task Settings**: Class-level overrides via `
|
36
|
+
2. **Task Settings**: Class-level overrides via `cmd_settings!`
|
25
37
|
3. **Runtime Parameters**: Instance-specific overrides during execution
|
26
38
|
|
27
39
|
> [!IMPORTANT]
|
@@ -35,22 +47,7 @@ Generate a configuration file using the Rails generator:
|
|
35
47
|
rails g cmdx:install
|
36
48
|
```
|
37
49
|
|
38
|
-
This creates `config/initializers/cmdx.rb` with default settings
|
39
|
-
|
40
|
-
```ruby
|
41
|
-
CMDx.configure do |config|
|
42
|
-
# Halt execution and raise fault on these result statuses when using `call!`
|
43
|
-
config.task_halt = CMDx::Result::FAILED
|
44
|
-
|
45
|
-
# Stop workflow execution when tasks return these statuses
|
46
|
-
# Note: Skipped tasks continue processing by default
|
47
|
-
config.workflow_halt = CMDx::Result::FAILED
|
48
|
-
|
49
|
-
# Logger with formatter - see available formatters at:
|
50
|
-
# https://github.com/drexed/cmdx/tree/main/lib/cmdx/log_formatters
|
51
|
-
config.logger = Logger.new($stdout, formatter: CMDx::LogFormatters::Line.new)
|
52
|
-
end
|
53
|
-
```
|
50
|
+
This creates `config/initializers/cmdx.rb` with default settings.
|
54
51
|
|
55
52
|
### Configuration Options
|
56
53
|
|
@@ -61,6 +58,8 @@ end
|
|
61
58
|
| `logger` | Logger | Line formatter | Logger instance for task execution logging |
|
62
59
|
| `middlewares` | MiddlewareRegistry | Empty registry | Global middleware registry applied to all tasks |
|
63
60
|
| `callbacks` | CallbackRegistry | Empty registry | Global callback registry applied to all tasks |
|
61
|
+
| `coercions` | CoercionRegistry | Built-in coercions | Global coercion registry for custom parameter types |
|
62
|
+
| `validators` | ValidatorRegistry | Built-in validators | Global validator registry for parameter validation |
|
64
63
|
|
65
64
|
### Global Middlewares
|
66
65
|
|
@@ -87,30 +86,70 @@ Configure callbacks that automatically apply to all tasks in your application:
|
|
87
86
|
CMDx.configure do |config|
|
88
87
|
# Add method callbacks
|
89
88
|
config.callbacks.register :before_execution, :log_task_start
|
90
|
-
config.callbacks.register :after_execution, :log_task_end
|
91
89
|
|
92
90
|
# Add callback instances
|
93
91
|
config.callbacks.register :on_success, NotificationCallback.new([:slack])
|
94
|
-
config.callbacks.register :on_failure, AlertCallback.new(severity: :critical)
|
95
92
|
|
96
93
|
# Add conditional callbacks
|
97
94
|
config.callbacks.register :on_failure, :page_admin, if: :production?
|
98
|
-
config.callbacks.register :before_validation, :skip_validation, unless: :validate_params?
|
99
95
|
|
100
96
|
# Add proc callbacks
|
101
|
-
config.callbacks.register :on_complete, proc { |task,
|
97
|
+
config.callbacks.register :on_complete, proc { |task, type|
|
102
98
|
Metrics.increment("task.#{task.class.name.underscore}.completed")
|
103
99
|
}
|
104
100
|
end
|
105
101
|
```
|
106
102
|
|
103
|
+
### Global Coercions
|
104
|
+
|
105
|
+
Configure custom coercions that automatically apply to all tasks in your application:
|
106
|
+
|
107
|
+
```ruby
|
108
|
+
CMDx.configure do |config|
|
109
|
+
# Add custom coercion classes
|
110
|
+
config.coercions.register :money, MoneyCoercion
|
111
|
+
|
112
|
+
# Add complex coercions with options support
|
113
|
+
config.coercions.register :tags, proc { |value, options|
|
114
|
+
separator = options[:separator] || ','
|
115
|
+
max_tags = options[:max_tags] || 10
|
116
|
+
|
117
|
+
tags = value.to_s.split(separator).map(&:strip).reject(&:empty?)
|
118
|
+
tags = tags.first(max_tags) if max_tags
|
119
|
+
tags.uniq
|
120
|
+
}
|
121
|
+
end
|
122
|
+
```
|
123
|
+
|
124
|
+
### Global Validators
|
125
|
+
|
126
|
+
Configure validators that automatically apply to all tasks in your application:
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
CMDx.configure do |config|
|
130
|
+
# Add validator classes
|
131
|
+
config.validators.register :email, EmailValidator
|
132
|
+
|
133
|
+
# Add complex validators with options support
|
134
|
+
config.validators.register :phone, proc { |value, options|
|
135
|
+
country = options.dig(:phone, :country) || "US"
|
136
|
+
case country
|
137
|
+
when "US"
|
138
|
+
value.match?(/\A\d{3}-\d{3}-\d{4}\z/)
|
139
|
+
else
|
140
|
+
value.match?(/\A\+?\d{10,15}\z/)
|
141
|
+
end
|
142
|
+
}
|
143
|
+
end
|
144
|
+
```
|
145
|
+
|
107
146
|
## Task Settings
|
108
147
|
|
109
|
-
Override global configuration for specific tasks or workflows using `
|
148
|
+
Override global configuration for specific tasks or workflows using `cmd_settings!`:
|
110
149
|
|
111
150
|
```ruby
|
112
151
|
class ProcessPaymentTask < CMDx::Task
|
113
|
-
|
152
|
+
cmd_settings!(
|
114
153
|
task_halt: ["failed"], # Only halt on failures
|
115
154
|
tags: ["payments", "critical"], # Add logging tags
|
116
155
|
logger: Rails.logger, # Use Rails logger
|
@@ -142,7 +181,7 @@ Configure halt behavior for workflows:
|
|
142
181
|
```ruby
|
143
182
|
class OrderProcessingWorkflow < CMDx::Workflow
|
144
183
|
# Strict workflow - halt on any failure
|
145
|
-
|
184
|
+
cmd_settings!(workflow_halt: ["failed", "skipped"])
|
146
185
|
|
147
186
|
process ValidateOrderTask
|
148
187
|
process ChargePaymentTask
|
@@ -160,14 +199,16 @@ CMDx.configuration.logger #=> <Logger instance>
|
|
160
199
|
CMDx.configuration.task_halt #=> "failed"
|
161
200
|
CMDx.configuration.middlewares #=> <MiddlewareRegistry instance>
|
162
201
|
CMDx.configuration.callbacks #=> <CallbackRegistry instance>
|
202
|
+
CMDx.configuration.coercions #=> <CoercionRegistry instance>
|
203
|
+
CMDx.configuration.validators #=> <ValidatorRegistry instance>
|
163
204
|
|
164
205
|
# Task-specific settings
|
165
206
|
class AnalyzeDataTask < CMDx::Task
|
166
|
-
|
207
|
+
cmd_settings!(tags: ["analytics"])
|
167
208
|
|
168
209
|
def call
|
169
|
-
tags =
|
170
|
-
halt_statuses =
|
210
|
+
tags = cmd_setting(:tags) # Gets ["analytics"]
|
211
|
+
halt_statuses = cmd_setting(:task_halt) # Gets global default
|
171
212
|
end
|
172
213
|
end
|
173
214
|
```
|
data/docs/getting_started.md
CHANGED
@@ -7,6 +7,7 @@ tasks to complex multi-step processes.
|
|
7
7
|
|
8
8
|
## Table of Contents
|
9
9
|
|
10
|
+
- [TLDR](#tldr)
|
10
11
|
- [Installation](#installation)
|
11
12
|
- [Quick Setup](#quick-setup)
|
12
13
|
- [Execution](#execution)
|
@@ -15,6 +16,16 @@ tasks to complex multi-step processes.
|
|
15
16
|
- [Building Workflows](#building-workflows)
|
16
17
|
- [Code Generation](#code-generation)
|
17
18
|
|
19
|
+
## TLDR
|
20
|
+
|
21
|
+
- **Installation** - Add `gem 'cmdx'` to Gemfile, run `rails g cmdx:install`
|
22
|
+
- **Tasks** - Ruby classes inheriting from `CMDx::Task` with `call` method
|
23
|
+
- **Execution** - Use `call` (returns result) or `call!` (raises on failure/skip)
|
24
|
+
- **Parameters** - Define with `required`/`optional` with type coercion and validation
|
25
|
+
- **Results** - Check `result.status` for success/skipped/failed outcomes
|
26
|
+
- **Workflows** - Orchestrate multiple tasks with `CMDx::Workflow`
|
27
|
+
- **Generators** - Use `rails g cmdx:task` and `rails g cmdx:workflow` for scaffolding
|
28
|
+
|
18
29
|
## Installation
|
19
30
|
|
20
31
|
Add CMDx to your Gemfile:
|
@@ -0,0 +1,148 @@
|
|
1
|
+
# Internationalization (i18n)
|
2
|
+
|
3
|
+
CMDx provides comprehensive internationalization support for all error messages, including parameter coercion errors, validation failures, and fault messages. All error text is automatically localized based on the current `I18n.locale`.
|
4
|
+
|
5
|
+
## Table of Contents
|
6
|
+
|
7
|
+
- [TLDR](#tldr)
|
8
|
+
- [Available Locales](#available-locales)
|
9
|
+
- [Fault Messages](#fault-messages)
|
10
|
+
- [Parameter Messages](#parameter-messages)
|
11
|
+
- [Coercion Messages](#coercion-messages)
|
12
|
+
- [Validation Messages](#validation-messages)
|
13
|
+
|
14
|
+
## TLDR
|
15
|
+
|
16
|
+
- **24 languages** - Built-in translations for major world languages
|
17
|
+
- **Automatic localization** - Based on `I18n.locale` setting
|
18
|
+
- **Complete coverage** - Coercion errors, validation failures, and fault messages
|
19
|
+
- **Custom overrides** - Parameter-specific messages override locale defaults
|
20
|
+
|
21
|
+
## Available Locales
|
22
|
+
|
23
|
+
CMDx includes built-in translations for 24 languages:
|
24
|
+
|
25
|
+
| Language | Locale | Language | Locale |
|
26
|
+
|----------|--------|----------|--------|
|
27
|
+
| English | `:en` | Russian | `:ru` |
|
28
|
+
| Spanish | `:es` | Arabic | `:ar` |
|
29
|
+
| French | `:fr` | Korean | `:ko` |
|
30
|
+
| German | `:de` | Dutch | `:nl` |
|
31
|
+
| Portuguese | `:pt` | Swedish | `:sv` |
|
32
|
+
| Italian | `:it` | Hindi | `:hi` |
|
33
|
+
| Japanese | `:ja` | Polish | `:pl` |
|
34
|
+
| Chinese | `:zh` | Turkish | `:tr` |
|
35
|
+
| Norwegian | `:no` | Danish | `:da` |
|
36
|
+
| Finnish | `:fi` | Greek | `:el` |
|
37
|
+
| Hebrew | `:he` | Thai | `:th` |
|
38
|
+
| Vietnamese | `:vi` | Czech | `:cs` |
|
39
|
+
|
40
|
+
## Fault Messages
|
41
|
+
|
42
|
+
Default fault messages from `skip!` and `fail!` methods are localized:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
class ProcessPaymentTask < CMDx::Task
|
46
|
+
def call
|
47
|
+
# When no reason is provided, uses localized default
|
48
|
+
fail! if payment_declined?
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# English
|
53
|
+
I18n.locale = :en
|
54
|
+
result = ProcessPaymentTask.call(payment_id: 123)
|
55
|
+
result.metadata[:reason] #=> "no reason given"
|
56
|
+
|
57
|
+
# Chinese
|
58
|
+
I18n.locale = :zh
|
59
|
+
result = ProcessPaymentTask.call(payment_id: 123)
|
60
|
+
result.metadata[:reason] #=> "未提供原因"
|
61
|
+
```
|
62
|
+
|
63
|
+
## Parameter Messages
|
64
|
+
|
65
|
+
Parameter required or undefined source errors are automatically localized:
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
class ProcessOrderTask < CMDx::Task
|
69
|
+
required :order_id, type: :integer
|
70
|
+
optional :user_name, source: :nonexistent_method
|
71
|
+
|
72
|
+
def call
|
73
|
+
# Task implementation
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# English locale
|
78
|
+
I18n.locale = :en
|
79
|
+
result = ProcessOrderTask.call({}) # Missing required parameter
|
80
|
+
result.metadata[:messages][:order_id] #=> ["is a required parameter"]
|
81
|
+
|
82
|
+
result = ProcessOrderTask.call(order_id: 123) # Undefined source method
|
83
|
+
result.metadata[:messages][:user_name] #=> ["delegates to undefined method nonexistent_method"]
|
84
|
+
|
85
|
+
# Spanish locale
|
86
|
+
I18n.locale = :es
|
87
|
+
result = ProcessOrderTask.call({}) # Missing required parameter
|
88
|
+
result.metadata[:messages][:order_id] #=> ["es un parámetro requerido"]
|
89
|
+
|
90
|
+
result = ProcessOrderTask.call(order_id: 123) # Undefined source method
|
91
|
+
result.metadata[:messages][:user_name] #=> ["delegado al método indefinido nonexistent_method"]
|
92
|
+
```
|
93
|
+
|
94
|
+
## Coercion Messages
|
95
|
+
|
96
|
+
Type conversion errors are automatically localized:
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
class ProcessOrderTask < CMDx::Task
|
100
|
+
required :order_id, type: :integer
|
101
|
+
required :amount, type: :float
|
102
|
+
|
103
|
+
def call
|
104
|
+
# Task implementation
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# English
|
109
|
+
I18n.locale = :en
|
110
|
+
result = ProcessOrderTask.call(order_id: "invalid", amount: "bad")
|
111
|
+
result.metadata[:messages][:order_id] #=> ["could not coerce into an integer"]
|
112
|
+
|
113
|
+
# Spanish
|
114
|
+
I18n.locale = :es
|
115
|
+
result = ProcessOrderTask.call(order_id: "invalid", amount: "bad")
|
116
|
+
result.metadata[:messages][:order_id] #=> ["no podía coacciona el valor a un integer"]
|
117
|
+
```
|
118
|
+
|
119
|
+
## Validation Messages
|
120
|
+
|
121
|
+
All validator error messages support internationalization:
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
class RegisterUserTask < CMDx::Task
|
125
|
+
required :email, format: { with: /@/ }
|
126
|
+
required :age, numeric: { min: 18 }
|
127
|
+
required :status, inclusion: { in: %w[active inactive] }
|
128
|
+
|
129
|
+
def call
|
130
|
+
# Task implementation
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# English
|
135
|
+
I18n.locale = :en
|
136
|
+
result = RegisterUserTask.call(email: "invalid", age: 16, status: "unknown")
|
137
|
+
result.metadata[:messages][:email] #=> ["is an invalid format"]
|
138
|
+
|
139
|
+
# Japanese
|
140
|
+
I18n.locale = :ja
|
141
|
+
result = RegisterUserTask.call(email: "invalid", age: 16, status: "unknown")
|
142
|
+
result.metadata[:messages][:email] #=> ["無効な形式です"]
|
143
|
+
```
|
144
|
+
|
145
|
+
---
|
146
|
+
|
147
|
+
- **Prev:** [Logging](logging.md)
|
148
|
+
- **Next:** [Testing](testing.md)
|
@@ -6,10 +6,19 @@ building reliable task execution flows and implementing proper error handling st
|
|
6
6
|
|
7
7
|
## Table of Contents
|
8
8
|
|
9
|
+
- [TLDR](#tldr)
|
9
10
|
- [Exception Handling Behavior](#exception-handling-behavior)
|
10
11
|
- [Bang Call (`call!`)](#bang-call-call)
|
11
12
|
- [Exception Classification](#exception-classification)
|
12
13
|
|
14
|
+
## TLDR
|
15
|
+
|
16
|
+
- **`call`** - Captures ALL exceptions, converts to failed results with metadata
|
17
|
+
- **`call!`** - Lets exceptions propagate (except CMDx faults based on task_halt config)
|
18
|
+
- **Exception info** - Available in `result.metadata[:original_exception]` and `result.metadata[:reason]`
|
19
|
+
- **Guaranteed results** - `call` always returns a result object, never raises
|
20
|
+
- **Fault vs Exception** - CMDx faults have special handling, other exceptions propagate in `call!`
|
21
|
+
|
13
22
|
## Exception Handling Behavior
|
14
23
|
|
15
24
|
### Non-bang Call (`call`)
|
@@ -178,7 +187,7 @@ CMDx faults have special handling in both call methods:
|
|
178
187
|
```ruby
|
179
188
|
class ProcessOrderWithHaltTask < CMDx::Task
|
180
189
|
# Configure to halt on failures
|
181
|
-
|
190
|
+
cmd_settings!(task_halt: [CMDx::Result::FAILED])
|
182
191
|
|
183
192
|
def call
|
184
193
|
fail!(reason: "This is a controlled failure")
|
@@ -7,6 +7,7 @@ sophisticated exception handling and control flow patterns.
|
|
7
7
|
|
8
8
|
## Table of Contents
|
9
9
|
|
10
|
+
- [TLDR](#tldr)
|
10
11
|
- [Fault Types](#fault-types)
|
11
12
|
- [Basic Exception Handling](#basic-exception-handling)
|
12
13
|
- [Fault Context Access](#fault-context-access)
|
@@ -15,6 +16,14 @@ sophisticated exception handling and control flow patterns.
|
|
15
16
|
- [Fault Chain Analysis](#fault-chain-analysis)
|
16
17
|
- [Task Halt Configuration](#task-halt-configuration)
|
17
18
|
|
19
|
+
## TLDR
|
20
|
+
|
21
|
+
- **Fault types** - `CMDx::Skipped` (from `skip!`) and `CMDx::Failed` (from `fail!`)
|
22
|
+
- **Exception handling** - Use `rescue CMDx::Fault` to catch both types
|
23
|
+
- **Full context** - Faults provide access to `result`, `task`, `context`, and `chain`
|
24
|
+
- **Advanced matching** - Use `for?(TaskClass)` and `matches? { |f| condition }` for specific fault handling
|
25
|
+
- **Propagation** - Use `throw!(result)` to bubble up failures while preserving fault context
|
26
|
+
|
18
27
|
## Fault Types
|
19
28
|
|
20
29
|
CMDx provides two primary fault types that inherit from the base `CMDx::Fault` class:
|
@@ -204,7 +213,7 @@ Control which statuses raise exceptions using the `task_halt` setting:
|
|
204
213
|
```ruby
|
205
214
|
class ProcessUserOrderTask < CMDx::Task
|
206
215
|
# Only failed tasks raise exceptions on call!
|
207
|
-
|
216
|
+
cmd_settings!(task_halt: [CMDx::Result::FAILED])
|
208
217
|
|
209
218
|
def call
|
210
219
|
skip!(reason: "Order already processed") if already_processed?
|
@@ -214,7 +223,7 @@ end
|
|
214
223
|
|
215
224
|
class ValidateUserDataTask < CMDx::Task
|
216
225
|
# Both failed and skipped tasks raise exceptions
|
217
|
-
|
226
|
+
cmd_settings!(task_halt: [CMDx::Result::FAILED, CMDx::Result::SKIPPED])
|
218
227
|
|
219
228
|
def call
|
220
229
|
skip!(reason: "Validation not required") if skip_validation?
|
data/docs/interruptions/halt.md
CHANGED
@@ -6,6 +6,7 @@ outcomes, each serving specific use cases in business logic.
|
|
6
6
|
|
7
7
|
## Table of Contents
|
8
8
|
|
9
|
+
- [TLDR](#tldr)
|
9
10
|
- [Skip (`skip!`)](#skip-skip)
|
10
11
|
- [Fail (`fail!`)](#fail-fail)
|
11
12
|
- [Metadata Enrichment](#metadata-enrichment)
|
@@ -13,6 +14,14 @@ outcomes, each serving specific use cases in business logic.
|
|
13
14
|
- [Exception Behavior](#exception-behavior)
|
14
15
|
- [The Reason Key](#the-reason-key)
|
15
16
|
|
17
|
+
## TLDR
|
18
|
+
|
19
|
+
- **`skip!`** - Controlled interruption when task shouldn't execute (not an error)
|
20
|
+
- **`fail!`** - Controlled interruption when task encounters an error condition
|
21
|
+
- **Metadata** - Both methods accept metadata hash: `skip!(reason: "...", error_code: "...")`
|
22
|
+
- **State changes** - Both transition to `interrupted` state, `skipped` or `failed` status
|
23
|
+
- **Exception behavior** - `call` returns results, `call!` raises `CMDx::Skipped/Failed` based on task_halt config
|
24
|
+
|
16
25
|
## Skip (`skip!`)
|
17
26
|
|
18
27
|
The `skip!` method indicates that a task did not meet the criteria to continue
|
data/docs/logging.md
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
CMDx provides comprehensive automatic logging for task execution with structured data, customizable formatters, and intelligent severity mapping. All task results are logged after completion with rich metadata for debugging and monitoring.
|
4
4
|
|
5
5
|
## Table of Contents
|
6
|
+
- [TLDR](#tldr)
|
6
7
|
- [Log Formatters](#log-formatters)
|
7
8
|
- [Standard Formatters](#standard-formatters)
|
8
9
|
- [Stylized Formatters (ANSI Colors)](#stylized-formatters-ansi-colors)
|
@@ -22,6 +23,15 @@ CMDx provides comprehensive automatic logging for task execution with structured
|
|
22
23
|
- [Multi-Destination Logging](#multi-destination-logging)
|
23
24
|
- [Log Data Structure](#log-data-structure)
|
24
25
|
|
26
|
+
## TLDR
|
27
|
+
|
28
|
+
- **Automatic logging** - All task results logged after completion with structured data
|
29
|
+
- **8 formatters** - Standard (Line, Json, KeyValue, Logstash, Raw) and Stylized (Pretty variants)
|
30
|
+
- **Configuration** - Global via `CMDx.configure` or task-specific via `cmd_settings!`
|
31
|
+
- **Severity mapping** - Success=INFO, Skipped=WARN, Failed=ERROR
|
32
|
+
- **Rich metadata** - Includes runtime, chain_id, status, context, and failure chains
|
33
|
+
- **Manual logging** - Access `logger` within tasks for custom messages
|
34
|
+
|
25
35
|
## Log Formatters
|
26
36
|
|
27
37
|
CMDx provides 8 built-in log formatters organized into standard and stylized categories:
|
@@ -83,7 +93,7 @@ Override logging settings for individual tasks:
|
|
83
93
|
|
84
94
|
```ruby
|
85
95
|
class SendEmailTask < CMDx::Task
|
86
|
-
|
96
|
+
cmd_settings!(
|
87
97
|
logger: Rails.logger,
|
88
98
|
log_formatter: CMDx::LogFormatters::Json.new,
|
89
99
|
log_level: Logger::WARN
|
@@ -96,7 +106,7 @@ end
|
|
96
106
|
|
97
107
|
# Base class with shared logging configuration
|
98
108
|
class ApplicationTask < CMDx::Task
|
99
|
-
|
109
|
+
cmd_settings!(
|
100
110
|
logger: Logger.new("log/tasks.log"),
|
101
111
|
log_formatter: CMDx::LogFormatters::Logstash.new,
|
102
112
|
log_level: Logger::INFO
|
@@ -169,7 +179,7 @@ class SlackLogFormatter
|
|
169
179
|
end
|
170
180
|
|
171
181
|
class SendNotificationTask < CMDx::Task
|
172
|
-
|
182
|
+
cmd_settings!(
|
173
183
|
logger: Logger.new("log/notifications.log", formatter: SlackLogFormatter.new)
|
174
184
|
)
|
175
185
|
end
|
@@ -242,4 +252,4 @@ CMDx logs contain comprehensive execution metadata:
|
|
242
252
|
---
|
243
253
|
|
244
254
|
- **Prev:** [Workflows](workflows.md)
|
245
|
-
- **Next:** [
|
255
|
+
- **Next:** [Internationalization (i18n)](internationalization.md)
|