cmdx 1.8.0 → 1.9.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.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/.DS_Store +0 -0
  3. data/.cursor/prompts/docs.md +3 -3
  4. data/.cursor/prompts/llms.md +1 -3
  5. data/.cursor/prompts/yardoc.md +1 -0
  6. data/.irbrc +14 -2
  7. data/CHANGELOG.md +64 -45
  8. data/LLM.md +159 -53
  9. data/README.md +26 -83
  10. data/docs/.DS_Store +0 -0
  11. data/docs/assets/favicon.ico +0 -0
  12. data/docs/assets/favicon.svg +1 -0
  13. data/docs/attributes/coercions.md +12 -24
  14. data/docs/attributes/defaults.md +3 -16
  15. data/docs/attributes/definitions.md +16 -30
  16. data/docs/attributes/naming.md +3 -13
  17. data/docs/attributes/transformations.md +63 -0
  18. data/docs/attributes/validations.md +14 -33
  19. data/docs/basics/chain.md +14 -23
  20. data/docs/basics/context.md +13 -22
  21. data/docs/basics/execution.md +8 -26
  22. data/docs/basics/setup.md +8 -19
  23. data/docs/callbacks.md +19 -32
  24. data/docs/deprecation.md +8 -25
  25. data/docs/getting_started.md +109 -76
  26. data/docs/index.md +132 -0
  27. data/docs/internationalization.md +6 -18
  28. data/docs/interruptions/exceptions.md +10 -16
  29. data/docs/interruptions/faults.md +8 -25
  30. data/docs/interruptions/halt.md +12 -27
  31. data/docs/logging.md +7 -17
  32. data/docs/middlewares.md +13 -29
  33. data/docs/outcomes/result.md +21 -38
  34. data/docs/outcomes/states.md +8 -22
  35. data/docs/outcomes/statuses.md +10 -21
  36. data/docs/stylesheets/extra.css +42 -0
  37. data/docs/tips_and_tricks.md +7 -46
  38. data/docs/workflows.md +23 -38
  39. data/examples/active_record_query_tagging.md +46 -0
  40. data/examples/paper_trail_whatdunnit.md +39 -0
  41. data/lib/cmdx/attribute.rb +88 -6
  42. data/lib/cmdx/attribute_registry.rb +20 -0
  43. data/lib/cmdx/attribute_value.rb +56 -10
  44. data/lib/cmdx/callback_registry.rb +31 -2
  45. data/lib/cmdx/chain.rb +34 -1
  46. data/lib/cmdx/coercion_registry.rb +18 -0
  47. data/lib/cmdx/coercions/array.rb +2 -0
  48. data/lib/cmdx/coercions/big_decimal.rb +3 -0
  49. data/lib/cmdx/coercions/boolean.rb +5 -0
  50. data/lib/cmdx/coercions/complex.rb +2 -0
  51. data/lib/cmdx/coercions/date.rb +4 -0
  52. data/lib/cmdx/coercions/date_time.rb +5 -0
  53. data/lib/cmdx/coercions/float.rb +2 -0
  54. data/lib/cmdx/coercions/hash.rb +4 -0
  55. data/lib/cmdx/coercions/integer.rb +2 -0
  56. data/lib/cmdx/coercions/rational.rb +2 -0
  57. data/lib/cmdx/coercions/string.rb +2 -0
  58. data/lib/cmdx/coercions/symbol.rb +2 -0
  59. data/lib/cmdx/coercions/time.rb +5 -0
  60. data/lib/cmdx/configuration.rb +119 -3
  61. data/lib/cmdx/context.rb +36 -0
  62. data/lib/cmdx/deprecator.rb +6 -3
  63. data/lib/cmdx/errors.rb +22 -0
  64. data/lib/cmdx/executor.rb +136 -7
  65. data/lib/cmdx/faults.rb +14 -0
  66. data/lib/cmdx/identifier.rb +2 -0
  67. data/lib/cmdx/locale.rb +3 -0
  68. data/lib/cmdx/log_formatters/json.rb +2 -0
  69. data/lib/cmdx/log_formatters/key_value.rb +2 -0
  70. data/lib/cmdx/log_formatters/line.rb +2 -0
  71. data/lib/cmdx/log_formatters/logstash.rb +2 -0
  72. data/lib/cmdx/log_formatters/raw.rb +2 -0
  73. data/lib/cmdx/middleware_registry.rb +20 -0
  74. data/lib/cmdx/middlewares/correlate.rb +11 -0
  75. data/lib/cmdx/middlewares/runtime.rb +4 -0
  76. data/lib/cmdx/middlewares/timeout.rb +4 -0
  77. data/lib/cmdx/pipeline.rb +24 -5
  78. data/lib/cmdx/railtie.rb +13 -0
  79. data/lib/cmdx/result.rb +133 -2
  80. data/lib/cmdx/task.rb +103 -8
  81. data/lib/cmdx/utils/call.rb +2 -0
  82. data/lib/cmdx/utils/condition.rb +3 -0
  83. data/lib/cmdx/utils/format.rb +5 -0
  84. data/lib/cmdx/validator_registry.rb +18 -0
  85. data/lib/cmdx/validators/exclusion.rb +2 -0
  86. data/lib/cmdx/validators/format.rb +2 -0
  87. data/lib/cmdx/validators/inclusion.rb +2 -0
  88. data/lib/cmdx/validators/length.rb +14 -0
  89. data/lib/cmdx/validators/numeric.rb +14 -0
  90. data/lib/cmdx/validators/presence.rb +2 -0
  91. data/lib/cmdx/version.rb +4 -1
  92. data/lib/cmdx/workflow.rb +10 -0
  93. data/lib/cmdx.rb +9 -0
  94. data/lib/generators/cmdx/locale_generator.rb +0 -1
  95. data/lib/generators/cmdx/templates/install.rb +9 -0
  96. data/mkdocs.yml +122 -0
  97. data/src/cmdx-dark-logo.png +0 -0
  98. data/src/cmdx-favicon.svg +1 -0
  99. data/src/cmdx-light-logo.png +0 -0
  100. data/src/cmdx-logo.svg +1 -0
  101. metadata +14 -3
  102. data/lib/cmdx/freezer.rb +0 -51
  103. data/src/cmdx-logo.png +0 -0
data/docs/index.md ADDED
@@ -0,0 +1,132 @@
1
+ # CMDx
2
+
3
+ Build business logic that's powerful, predictable, and maintainable.
4
+
5
+ [![Version](https://img.shields.io/gem/v/cmdx)](https://rubygems.org/gems/cmdx)
6
+ [![Build](https://github.com/drexed/cmdx/actions/workflows/ci.yml/badge.svg)](https://github.com/drexed/cmdx/actions/workflows/ci.yml)
7
+ [![License](https://img.shields.io/github/license/drexed/cmdx)](https://github.com/drexed/cmdx/blob/main/LICENSE.txt)
8
+
9
+ ---
10
+
11
+ Say goodbye to messy service objects. CMDx helps you design business logic with clarity and consistency—build faster, debug easier, and ship with confidence.
12
+
13
+ !!! note
14
+
15
+ Documentation reflects the latest code on `main`. For version-specific documentation, please refer to the `docs/` directory within that version's tag.
16
+
17
+ ## Requirements
18
+
19
+ - Ruby: MRI 3.1+ or JRuby 9.4+.
20
+
21
+ CMDx works with any Ruby framework. Rails support is built-in, but it's framework-agnostic at its core.
22
+
23
+ ## Installation
24
+
25
+ ```sh
26
+ gem install cmdx
27
+ # - or -
28
+ bundle add cmdx
29
+ ```
30
+
31
+ ## Quick Example
32
+
33
+ Build powerful business logic in four simple steps:
34
+
35
+ ### 1. Compose
36
+
37
+ === "Full Featured Task"
38
+
39
+ ```ruby
40
+ class AnalyzeMetrics < CMDx::Task
41
+ register :middleware, CMDx::Middlewares::Correlate, id: -> { Current.request_id }
42
+
43
+ on_success :track_analysis_completion!
44
+
45
+ required :dataset_id, type: :integer, numeric: { min: 1 }
46
+ optional :analysis_type, default: "standard"
47
+
48
+ def work
49
+ if dataset.nil?
50
+ fail!("Dataset not found", code: 404)
51
+ elsif dataset.unprocessed?
52
+ skip!("Dataset not ready for analysis")
53
+ else
54
+ context.result = PValueAnalyzer.execute(dataset:, analysis_type:)
55
+ context.analyzed_at = Time.now
56
+
57
+ SendAnalyzedEmail.execute(user_id: Current.account.manager_id)
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ def dataset
64
+ @dataset ||= Dataset.find_by(id: dataset_id)
65
+ end
66
+
67
+ def track_analysis_completion!
68
+ dataset.update!(analysis_result_id: context.result.id)
69
+ end
70
+ end
71
+ ```
72
+
73
+ === "Minimum Viable Task"
74
+
75
+ ```ruby
76
+ class SendAnalyzedEmail < CMDx::Task
77
+ def work
78
+ user = User.find(context.user_id)
79
+ MetricsMailer.analyzed(user).deliver_now
80
+ end
81
+ end
82
+ ```
83
+
84
+ ### 2. Execute
85
+
86
+ ```ruby
87
+ result = AnalyzeMetrics.execute(
88
+ dataset_id: 123,
89
+ "analysis_type" => "advanced"
90
+ )
91
+ ```
92
+
93
+ ### 3. React
94
+
95
+ ```ruby
96
+ if result.success?
97
+ puts "Metrics analyzed at #{result.context.analyzed_at}"
98
+ elsif result.skipped?
99
+ puts "Skipping analyzation due to: #{result.reason}"
100
+ elsif result.failed?
101
+ puts "Analyzation failed due to: #{result.reason} with code #{result.metadata[:code]}"
102
+ end
103
+ ```
104
+
105
+ ### 4. Observe
106
+
107
+ ```log
108
+ I, [2022-07-17T18:42:37.000000 #3784] INFO -- CMDx:
109
+ index=1 chain_id="018c2b95-23j4-2kj3-32kj-3n4jk3n4jknf" type="Task" class="SendAnalyzedEmail" state="complete" status="success" metadata={runtime: 347}
110
+
111
+ I, [2022-07-17T18:43:15.000000 #3784] INFO -- CMDx:
112
+ index=0 chain_id="018c2b95-b764-7615-a924-cc5b910ed1e5" type="Task" class="AnalyzeMetrics" state="complete" status="success" metadata={runtime: 187}
113
+ ```
114
+
115
+ Ready to dive in? Check out the [Getting Started](getting_started.md) guide to learn more.
116
+
117
+ ## Ecosystem
118
+
119
+ - [cmdx-rspec](https://github.com/drexed/cmdx-rspec) - RSpec test matchers
120
+
121
+ For backwards compatibility of certain functionality:
122
+
123
+ - [cmdx-i18n](https://github.com/drexed/cmdx-i18n) - 85+ translations, `v1.5.0` - `v1.6.2`
124
+ - [cmdx-parallel](https://github.com/drexed/cmdx-parallel) - Parallel workflow tasks, `v1.6.1` - `v1.6.2`
125
+
126
+ ## Contributing
127
+
128
+ Bug reports and pull requests are welcome at <https://github.com/drexed/cmdx>. We're committed to fostering a welcoming, collaborative community. Please follow our [code of conduct](CODE_OF_CONDUCT.md).
129
+
130
+ ## License
131
+
132
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -1,17 +1,10 @@
1
1
  # Internationalization (i18n)
2
2
 
3
- CMDx provides comprehensive internationalization support for all error messages, attribute validation failures, coercion errors, and fault messages. All user-facing text is automatically localized based on the current `I18n.locale`, ensuring your applications can serve global audiences with native-language error reporting.
3
+ CMDx supports 90+ languages out of the box for all error messages, validations, coercions, and faults. Error messages automatically adapt to the current `I18n.locale`, making it easy to build applications for global audiences.
4
4
 
5
- ## Table of Contents
5
+ ## Usage
6
6
 
7
- - [Localization](#localization)
8
- - [Configuration](#configuration)
9
- - [Local Copies](#local-copies)
10
- - [Available Locales](#available-locales)
11
-
12
- ## Localization
13
-
14
- CMDx automatically localizes all error messages based on the `I18n.locale` setting.
7
+ All error messages are automatically localized based on your current locale:
15
8
 
16
9
  ```ruby
17
10
  class ProcessQuote < CMDx::Task
@@ -30,11 +23,11 @@ end
30
23
 
31
24
  ## Configuration
32
25
 
33
- Localization is handled by the `I18n` gem. In Rails applications, locales are loaded automatically and managed via the `I18n.available_locales` setting.
26
+ CMDx uses the `I18n` gem for localization. In Rails, locales load automatically.
34
27
 
35
- ### Local Copies
28
+ ### Copy Locale Files
36
29
 
37
- Execute the following command to copy any locale into the Rails applications `config/locales` directory:
30
+ Copy locale files to your Rails application's `config/locales` directory:
38
31
 
39
32
  ```bash
40
33
  rails generate cmdx:locale [LOCALE]
@@ -131,8 +124,3 @@ rails generate cmdx:locale fr
131
124
  - zh-HK - Chinese (Hong Kong)
132
125
  - zh-TW - Chinese (Traditional)
133
126
  - zh-YUE - Chinese (Yue)
134
-
135
- ---
136
-
137
- - **Prev:** [Logging](logging.md)
138
- - **Next:** [Deprecation](deprecation.md)
@@ -1,21 +1,16 @@
1
1
  # Interruptions - Exceptions
2
2
 
3
- CMDx provides robust exception handling that differs between the `execute` and `execute!` methods. Understanding how unhandled exceptions are processed is crucial for building reliable task execution flows and implementing proper error handling strategies.
4
-
5
- ## Table of Contents
6
-
7
- - [Exception Handling](#exception-handling)
8
- - [Non-bang execution](#non-bang-execution)
9
- - [Bang execution](#bang-execution)
3
+ Exception handling differs between `execute` and `execute!`. Choose the method that matches your error handling strategy.
10
4
 
11
5
  ## Exception Handling
12
6
 
13
- > [!IMPORTANT]
14
- > When designing tasks try not to `raise` your own exceptions directly, instead use `skip!` or `fail!` to signal intent clearly.
7
+ !!! warning "Important"
8
+
9
+ Prefer `skip!` and `fail!` over raising exceptions—they signal intent more clearly.
15
10
 
16
11
  ### Non-bang execution
17
12
 
18
- The `execute` method captures **all** unhandled exceptions and converts them to failed results, ensuring predictable behavior and consistent result processing.
13
+ Captures all exceptions and returns them as failed results:
19
14
 
20
15
  ```ruby
21
16
  class CompressDocument < CMDx::Task
@@ -33,9 +28,13 @@ result.reason #=> "[ActiveRecord::NotFoundError] record not found"
33
28
  result.cause #=> <ActiveRecord::NotFoundError>
34
29
  ```
35
30
 
31
+ !!! note
32
+
33
+ Use `exception_handler` with `execute` to send exceptions to APM tools before they become failed results.
34
+
36
35
  ### Bang execution
37
36
 
38
- The `execute!` method allows unhandled exceptions to propagate, enabling standard Ruby exception handling while respecting CMDx fault configuration.
37
+ Lets exceptions propagate naturally for standard Ruby error handling:
39
38
 
40
39
  ```ruby
41
40
  class CompressDocument < CMDx::Task
@@ -51,8 +50,3 @@ rescue ActiveRecord::NotFoundError => e
51
50
  puts "Handle exception: #{e.message}"
52
51
  end
53
52
  ```
54
-
55
- ---
56
-
57
- - **Prev:** [Interruptions - Faults](faults.md)
58
- - **Next:** [Outcomes - Result](../outcomes/result.md)
@@ -1,19 +1,6 @@
1
1
  # Interruptions - Faults
2
2
 
3
- Faults are exception mechanisms that halt task execution via `skip!` and `fail!` methods. When tasks execute with the `execute!` method, fault exceptions matching the task's interruption status are raised, enabling sophisticated exception handling and control flow patterns.
4
-
5
- ## Table of Contents
6
-
7
- - [Fault Types](#fault-types)
8
- - [Fault Handling](#fault-handling)
9
- - [Data Access](#data-access)
10
- - [Advanced Matching](#advanced-matching)
11
- - [Task-Specific Matching](#task-specific-matching)
12
- - [Custom Logic Matching](#custom-logic-matching)
13
- - [Fault Propagation](#fault-propagation)
14
- - [Basic Propagation](#basic-propagation)
15
- - [Additional Metadata](#additional-metadata)
16
- - [Chain Analysis](#chain-analysis)
3
+ Faults are exceptions raised by `execute!` when tasks halt. They carry rich context about execution state, enabling sophisticated error handling patterns.
17
4
 
18
5
  ## Fault Types
19
6
 
@@ -23,8 +10,9 @@ Faults are exception mechanisms that halt task execution via `skip!` and `fail!`
23
10
  | `CMDx::SkipFault` | `skip!` method | Optional processing, early returns |
24
11
  | `CMDx::FailFault` | `fail!` method | Validation errors, processing failures |
25
12
 
26
- > [!IMPORTANT]
27
- > All fault exceptions inherit from `CMDx::Fault` and provide access to the complete task execution context including result, task, context, and chain information.
13
+ !!! warning "Important"
14
+
15
+ All faults inherit from `CMDx::Fault` and expose result, task, context, and chain data.
28
16
 
29
17
  ## Fault Handling
30
18
 
@@ -45,7 +33,7 @@ end
45
33
 
46
34
  ## Data Access
47
35
 
48
- Faults provide comprehensive access to execution context, eg:
36
+ Access rich execution data from fault exceptions:
49
37
 
50
38
  ```ruby
51
39
  begin
@@ -74,7 +62,7 @@ end
74
62
 
75
63
  ### Task-Specific Matching
76
64
 
77
- Use `for?` to handle faults only from specific task classes, enabling targeted exception handling in complex workflows.
65
+ Handle faults only from specific tasks using `for?`:
78
66
 
79
67
  ```ruby
80
68
  begin
@@ -104,7 +92,7 @@ end
104
92
 
105
93
  ## Fault Propagation
106
94
 
107
- Use `throw!` to propagate failures while preserving fault context and maintaining the error chain for debugging.
95
+ Propagate failures with `throw!` to preserve context and maintain the error chain:
108
96
 
109
97
  ### Basic Propagation
110
98
 
@@ -151,7 +139,7 @@ end
151
139
 
152
140
  ## Chain Analysis
153
141
 
154
- Results provide methods to analyze fault propagation and identify original failure sources in complex execution chains.
142
+ Trace fault origins and propagation through the execution chain:
155
143
 
156
144
  ```ruby
157
145
  result = DocumentWorkflow.execute(invalid_data)
@@ -179,8 +167,3 @@ if result.failed?
179
167
  end
180
168
  end
181
169
  ```
182
-
183
- ---
184
-
185
- - **Prev:** [Interruptions - Halt](halt.md)
186
- - **Next:** [Interruptions - Exceptions](exceptions.md)
@@ -1,25 +1,14 @@
1
1
  # Interruptions - Halt
2
2
 
3
- Halting stops task execution with explicit intent signaling. Tasks provide two primary halt methods that control execution flow and result in different outcomes.
4
-
5
- ## Table of Contents
6
-
7
- - [Skipping](#skipping)
8
- - [Failing](#failing)
9
- - [Metadata Enrichment](#metadata-enrichment)
10
- - [State Transitions](#state-transitions)
11
- - [Execution Behavior](#execution-behavior)
12
- - [Non-bang execution](#non-bang-execution)
13
- - [Bang execution](#bang-execution)
14
- - [Best Practices](#best-practices)
15
- - [Manual Errors](#manual-errors)
3
+ Stop task execution intentionally using `skip!` or `fail!`. Both methods signal clear intent about why execution stopped.
16
4
 
17
5
  ## Skipping
18
6
 
19
- `skip!` communicates that the task is to be intentionally bypassed. This represents a controlled, intentional interruption where the task determines that execution is not necessary or appropriate.
7
+ Use `skip!` when the task doesn't need to run. It's a no-op, not an error.
8
+
9
+ !!! warning "Important"
20
10
 
21
- > [!IMPORTANT]
22
- > Skipping is a no-op, not a failure or error and are considered successful outcomes.
11
+ Skipped tasks are considered "good" outcomes—they succeeded by doing nothing.
23
12
 
24
13
  ```ruby
25
14
  class ProcessInventory < CMDx::Task
@@ -54,7 +43,7 @@ result.reason #=> "Warehouse closed"
54
43
 
55
44
  ## Failing
56
45
 
57
- `fail!` communicates that the task encountered an impediment that prevents successful completion. This represents controlled failure where the task explicitly determines that execution cannot continue.
46
+ Use `fail!` when the task can't complete successfully. It signals controlled, intentional failure:
58
47
 
59
48
  ```ruby
60
49
  class ProcessRefund < CMDx::Task
@@ -89,7 +78,7 @@ result.reason #=> "Refund period has expired"
89
78
 
90
79
  ## Metadata Enrichment
91
80
 
92
- Both halt methods accept metadata to provide additional context about the interruption. Metadata is stored as a hash and becomes available through the result object.
81
+ Enrich halt calls with metadata for better debugging and error handling:
93
82
 
94
83
  ```ruby
95
84
  class ProcessRenewal < CMDx::Task
@@ -189,7 +178,7 @@ end
189
178
 
190
179
  ## Best Practices
191
180
 
192
- Always try to provide a `reason` when using halt methods. This provides clear context for debugging and creates meaningful exception messages.
181
+ Always provide a reason for better debugging and clearer exception messages:
193
182
 
194
183
  ```ruby
195
184
  # Good: Clear, specific reason
@@ -207,10 +196,11 @@ fail! #=> "Unspecified"
207
196
 
208
197
  ## Manual Errors
209
198
 
210
- There are rare cases where you need to manually assign errors.
199
+ For rare cases, manually add errors before halting:
211
200
 
212
- > [!IMPORTANT]
213
- > Keep in mind you will still need to initiate a fault if a stoppage of work is required.
201
+ !!! warning "Important"
202
+
203
+ Manual errors don't stop execution—you still need to call `fail!` or `skip!`.
214
204
 
215
205
  ```ruby
216
206
  class ProcessRenewal < CMDx::Task
@@ -224,8 +214,3 @@ class ProcessRenewal < CMDx::Task
224
214
  end
225
215
  end
226
216
  ```
227
-
228
- ---
229
-
230
- - **Prev:** [Basics - Chain](../basics/chain.md)
231
- - **Next:** [Interruptions - Faults](faults.md)
data/docs/logging.md CHANGED
@@ -1,16 +1,10 @@
1
1
  # Logging
2
2
 
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
-
5
- ## Table of Contents
6
-
7
- - [Formatters](#formatters)
8
- - [Structure](#structure)
9
- - [Usage](#usage)
3
+ CMDx automatically logs every task execution with structured data, making debugging and monitoring effortless. Choose from multiple formatters to match your logging infrastructure.
10
4
 
11
5
  ## Formatters
12
6
 
13
- CMDx supports multiple log formatters to integrate with various logging systems:
7
+ Choose the format that works best for your logging system:
14
8
 
15
9
  | Formatter | Use Case | Output Style |
16
10
  |-----------|----------|--------------|
@@ -40,12 +34,13 @@ E, [2022-07-17T18:43:15.000000 #3784] ERROR -- BillingWorkflow:
40
34
  index=3 chain_id="018c2b95-b764-7615-a924-cc5b910ed1e5" type="Task" class="BillingWorkflow" state="interrupted" status="failed" caused_failure={index: 2, class: "CalculateTax", status: "failed"} threw_failure={index: 1, class: "ValidateCustomer", status: "failed"}
41
35
  ```
42
36
 
43
- > [!TIP]
44
- > Logging can be used as low-level eventing system, ingesting all tasks performed within a small action or long running request. This ie where correlation is especially handy.
37
+ !!! tip
38
+
39
+ Use logging as a low-level event stream to track all tasks in a request. Combine with correlation for powerful distributed tracing.
45
40
 
46
41
  ## Structure
47
42
 
48
- All log entries include comprehensive execution metadata. Field availability depends on execution context and outcome.
43
+ Every log entry includes rich metadata. Available fields depend on execution context and outcome.
49
44
 
50
45
  ### Core Fields
51
46
 
@@ -86,7 +81,7 @@ All log entries include comprehensive execution metadata. Field availability dep
86
81
 
87
82
  ## Usage
88
83
 
89
- Tasks have access to the frameworks logger.
84
+ Access the framework logger directly within tasks:
90
85
 
91
86
  ```ruby
92
87
  class ProcessSubscription < CMDx::Task
@@ -97,8 +92,3 @@ class ProcessSubscription < CMDx::Task
97
92
  end
98
93
  end
99
94
  ```
100
-
101
- ---
102
-
103
- - **Prev:** [Middlewares](middlewares.md)
104
- - **Next:** [Internationalization (i18n)](internationalization.md)
data/docs/middlewares.md CHANGED
@@ -1,27 +1,16 @@
1
1
  # Middlewares
2
2
 
3
- Middleware provides Rack-style wrappers around task execution for cross-cutting concerns like authentication, logging, caching, and error handling.
3
+ Wrap task execution with middleware for cross-cutting concerns like authentication, caching, timeouts, and monitoring. Think Rack middleware, but for your business logic.
4
4
 
5
- Check out the [Getting Started](https://github.com/drexed/cmdx/blob/main/docs/getting_started.md#middlewares) docs for global configuration.
5
+ See [Global Configuration](getting_started.md#middlewares) for framework-wide setup.
6
6
 
7
- ## Table of Contents
7
+ ## Execution Order
8
8
 
9
- - [Order](#order)
10
- - [Declarations](#declarations)
11
- - [Proc or Lambda](#proc-or-lambda)
12
- - [Class or Module](#class-or-module)
13
- - [Removals](#removals)
14
- - [Built-in](#built-in)
15
- - [Timeout](#timeout)
16
- - [Correlate](#correlate)
17
- - [Runtime](#runtime)
9
+ Middleware wraps task execution in layers, like an onion:
18
10
 
19
- ## Order
11
+ !!! note
20
12
 
21
- Middleware executes in a nested fashion, creating an onion-like execution pattern:
22
-
23
- > [!NOTE]
24
- > Middleware executes in the order they are registered, with the first registered middleware being the outermost wrapper.
13
+ First registered = outermost wrapper. They execute in registration order.
25
14
 
26
15
  ```ruby
27
16
  class ProcessCampaign < CMDx::Task
@@ -97,10 +86,11 @@ end
97
86
 
98
87
  ## Removals
99
88
 
100
- Class and Module based declarations can be removed at a global and task level.
89
+ Remove class or module-based middleware globally or per-task:
90
+
91
+ !!! warning
101
92
 
102
- > [!WARNING]
103
- > Only one removal operation is allowed per `deregister` call. Multiple removals require separate calls.
93
+ Each `deregister` call removes one middleware. Use multiple calls for batch removals.
104
94
 
105
95
  ```ruby
106
96
  class ProcessCampaign < CMDx::Task
@@ -113,7 +103,7 @@ end
113
103
 
114
104
  ### Timeout
115
105
 
116
- Ensures task execution doesn't exceed a specified time limit:
106
+ Prevent tasks from running too long:
117
107
 
118
108
  ```ruby
119
109
  class ProcessReport < CMDx::Task
@@ -149,7 +139,7 @@ result.metadata #=> { limit: 3 }
149
139
 
150
140
  ### Correlate
151
141
 
152
- Tags tasks with a global correlation ID for distributed tracing:
142
+ Add correlation IDs for distributed tracing and request tracking:
153
143
 
154
144
  ```ruby
155
145
  class ProcessExport < CMDx::Task
@@ -179,8 +169,7 @@ result.metadata #=> { correlation_id: "550e8400-e29b-41d4-a716-446655440000" }
179
169
 
180
170
  ### Runtime
181
171
 
182
- The runtime middleware tags tasks with how long it took to execute the task.
183
- The calculation uses a monotonic clock and the time is returned in milliseconds.
172
+ Track task execution time in milliseconds using a monotonic clock:
184
173
 
185
174
  ```ruby
186
175
  class PerformanceMonitoringCheck
@@ -200,8 +189,3 @@ end
200
189
  result = ProcessExport.execute
201
190
  result.metadata #=> { runtime: 1247 } (ms)
202
191
  ```
203
-
204
- ---
205
-
206
- - **Prev:** [Callbacks](callbacks.md)
207
- - **Next:** [Logging](logging.md)
@@ -1,27 +1,14 @@
1
1
  # Outcomes - Result
2
2
 
3
- The result object is the comprehensive return value of task execution, providing complete information about the execution outcome, state, timing, and any data produced during the task lifecycle. Results serve as the primary interface for inspecting task execution outcomes and chaining task operations.
4
-
5
- ## Table of Contents
6
-
7
- - [Result Attributes](#result-attributes)
8
- - [Lifecycle Information](#lifecycle-information)
9
- - [Outcome Analysis](#outcome-analysis)
10
- - [Chain Analysis](#chain-analysis)
11
- - [Index and Position](#index-and-position)
12
- - [Block Yield](#block-yield)
13
- - [Handlers](#handlers)
14
- - [Pattern Matching](#pattern-matching)
15
- - [Array Pattern](#array-pattern)
16
- - [Hash Pattern](#hash-pattern)
17
- - [Pattern Guards](#pattern-guards)
3
+ Results are your window into task execution. They expose everything: outcome, state, timing, context, and metadata.
18
4
 
19
5
  ## Result Attributes
20
6
 
21
- Every result provides access to essential execution information:
7
+ Access essential execution information:
22
8
 
23
- > [!IMPORTANT]
24
- > Result objects are immutable after task execution completes and reflect the final state.
9
+ !!! warning "Important"
10
+
11
+ Results are immutable after execution completes.
25
12
 
26
13
  ```ruby
27
14
  result = BuildApplication.execute(version: "1.2.3")
@@ -43,7 +30,7 @@ result.metadata #=> { error_code: "BUILD_TOOL.NOT_FOUND" }
43
30
 
44
31
  ## Lifecycle Information
45
32
 
46
- Results provide comprehensive methods for checking execution state and status:
33
+ Check execution state and status with predicate methods:
47
34
 
48
35
  ```ruby
49
36
  result = BuildApplication.execute(version: "1.2.3")
@@ -65,7 +52,7 @@ result.bad? #=> false (skipped or failed)
65
52
 
66
53
  ## Outcome Analysis
67
54
 
68
- Results provide unified outcome determination depending on the fault causal chain:
55
+ Get a unified outcome string combining state and status:
69
56
 
70
57
  ```ruby
71
58
  result = BuildApplication.execute(version: "1.2.3")
@@ -75,7 +62,7 @@ result.outcome #=> "success" (state and status)
75
62
 
76
63
  ## Chain Analysis
77
64
 
78
- Use these methods to trace the root cause of faults or trace the cause points.
65
+ Trace fault origins and propagation:
79
66
 
80
67
  ```ruby
81
68
  result = DeploymentWorkflow.execute(app_name: "webapp")
@@ -116,7 +103,7 @@ result.chain.results[result.index] == result #=> true
116
103
 
117
104
  ## Block Yield
118
105
 
119
- Implement conditional logic using a block expression that yields a result for complete encapsulation.
106
+ Execute code with direct result access:
120
107
 
121
108
  ```ruby
122
109
  BuildApplication.execute(version: "1.2.3") do |result|
@@ -132,34 +119,35 @@ end
132
119
 
133
120
  ## Handlers
134
121
 
135
- Use result handlers for clean, functional-style conditional logic. Handlers return the result object, enabling method chaining and fluent interfaces.
122
+ Handle outcomes with functional-style methods. Handlers return the result for chaining:
136
123
 
137
124
  ```ruby
138
125
  result = BuildApplication.execute(version: "1.2.3")
139
126
 
140
127
  # Status-based handlers
141
128
  result
142
- .on_success { |result| notify_deployment_ready(result) }
143
- .on_failed { |result| handle_build_failure(result) }
144
- .on_skipped { |result| log_skip_reason(result) }
129
+ .handle_success { |result| notify_deployment_ready(result) }
130
+ .handle_failed { |result| handle_build_failure(result) }
131
+ .handle_skipped { |result| log_skip_reason(result) }
145
132
 
146
133
  # State-based handlers
147
134
  result
148
- .on_complete { |result| update_build_status(result) }
149
- .on_interrupted { |result| cleanup_partial_artifacts(result) }
135
+ .handle_complete { |result| update_build_status(result) }
136
+ .handle_interrupted { |result| cleanup_partial_artifacts(result) }
150
137
 
151
138
  # Outcome-based handlers
152
139
  result
153
- .on_good { |result| increment_success_counter(result) }
154
- .on_bad { |result| alert_operations_team(result) }
140
+ .handle_good { |result| increment_success_counter(result) }
141
+ .handle_bad { |result| alert_operations_team(result) }
155
142
  ```
156
143
 
157
144
  ## Pattern Matching
158
145
 
159
- Results support Ruby's pattern matching through array and hash deconstruction:
146
+ Use Ruby 3.0+ pattern matching for elegant outcome handling:
147
+
148
+ !!! warning "Important"
160
149
 
161
- > [!IMPORTANT]
162
- > Pattern matching requires Ruby 3.0+
150
+ Pattern matching works with both array and hash deconstruction.
163
151
 
164
152
  ### Array Pattern
165
153
 
@@ -203,8 +191,3 @@ in { runtime: time } if time > performance_threshold
203
191
  investigate_build_performance(result)
204
192
  end
205
193
  ```
206
-
207
- ---
208
-
209
- - **Prev:** [Interruptions - Exceptions](../interruptions/exceptions.md)
210
- - **Next:** [Outcomes - States](states.md)