cmdx 1.13.0 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +84 -76
- data/LICENSE.txt +3 -20
- data/README.md +8 -7
- data/lib/cmdx/attribute.rb +21 -5
- data/lib/cmdx/context.rb +16 -0
- data/lib/cmdx/executor.rb +9 -9
- data/lib/cmdx/result.rb +27 -7
- data/lib/cmdx/task.rb +19 -0
- data/lib/cmdx/version.rb +1 -1
- data/mkdocs.yml +62 -36
- metadata +3 -57
- data/.cursor/prompts/docs.md +0 -12
- data/.cursor/prompts/llms.md +0 -8
- data/.cursor/prompts/rspec.md +0 -24
- data/.cursor/prompts/yardoc.md +0 -15
- data/.cursor/rules/cursor-instructions.mdc +0 -68
- data/.irbrc +0 -18
- data/.rspec +0 -4
- data/.rubocop.yml +0 -95
- data/.ruby-version +0 -1
- data/.yard-lint.yml +0 -174
- data/.yardopts +0 -7
- data/docs/.DS_Store +0 -0
- data/docs/assets/favicon.ico +0 -0
- data/docs/assets/favicon.svg +0 -1
- data/docs/attributes/coercions.md +0 -155
- data/docs/attributes/defaults.md +0 -77
- data/docs/attributes/definitions.md +0 -283
- data/docs/attributes/naming.md +0 -68
- data/docs/attributes/transformations.md +0 -63
- data/docs/attributes/validations.md +0 -336
- data/docs/basics/chain.md +0 -108
- data/docs/basics/context.md +0 -121
- data/docs/basics/execution.md +0 -152
- data/docs/basics/setup.md +0 -107
- data/docs/callbacks.md +0 -157
- data/docs/configuration.md +0 -314
- data/docs/deprecation.md +0 -143
- data/docs/getting_started.md +0 -137
- data/docs/index.md +0 -134
- data/docs/internationalization.md +0 -126
- data/docs/interruptions/exceptions.md +0 -52
- data/docs/interruptions/faults.md +0 -169
- data/docs/interruptions/halt.md +0 -216
- data/docs/logging.md +0 -90
- data/docs/middlewares.md +0 -191
- data/docs/outcomes/result.md +0 -197
- data/docs/outcomes/states.md +0 -66
- data/docs/outcomes/statuses.md +0 -65
- data/docs/retries.md +0 -121
- data/docs/stylesheets/extra.css +0 -42
- data/docs/tips_and_tricks.md +0 -157
- data/docs/workflows.md +0 -226
- data/examples/active_record_database_transaction.md +0 -27
- data/examples/active_record_query_tagging.md +0 -46
- data/examples/flipper_feature_flags.md +0 -50
- data/examples/paper_trail_whatdunnit.md +0 -39
- data/examples/redis_idempotency.md +0 -71
- data/examples/sentry_error_tracking.md +0 -46
- data/examples/sidekiq_async_execution.md +0 -29
- data/examples/stoplight_circuit_breaker.md +0 -36
- data/src/cmdx-dark-logo.png +0 -0
- data/src/cmdx-favicon.svg +0 -1
- data/src/cmdx-light-logo.png +0 -0
- data/src/cmdx-logo.svg +0 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 620c2c00dd483c6a4122c7b5acbbe6cf7a07d22260d0331d6f1d54b571ef7648
|
|
4
|
+
data.tar.gz: aff47b340a77b052bc4cd2e201068044a443c1d8f4609163fa45025bdba25d00
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a8f6fec277ff0198937013c25a1a1c753d4cf5100ff4920c834dc92fba8df7d2adc1ef3fbcff91c999f1af8c4676c3e8702c71a29a3402efcf36d4a0236163ba
|
|
7
|
+
data.tar.gz: 2233517633c8d9afaafb7a44878b6b3fe0939dabcbe647ceafd9e7ca04450ee1e5e9f6b6f5adb2de58c305b0c2c0940e74ee2d7290f0eb202bda429d76b66992
|
data/CHANGELOG.md
CHANGED
|
@@ -4,175 +4,183 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
-
## [
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- Add Ruby 4.0 compatibility
|
|
11
|
+
- Add `Context#clear!` method to remove all context data
|
|
12
|
+
- Add `Task.attribute_schema` class method for attribute introspection
|
|
13
|
+
- Add `#to_h` method for attribute serialization
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- **BREAKING**: Switch license from MIT to LGPLv3
|
|
17
|
+
- Replace `instance_eval` with `define_singleton_method` for attribute method definitions
|
|
18
|
+
- Move retry count from metadata to result object
|
|
19
|
+
- Exclude non-essential files from gem package
|
|
20
|
+
|
|
21
|
+
### Removed
|
|
22
|
+
- Remove public `Result#rolled_back!` method to hide internal implementation
|
|
8
23
|
|
|
9
24
|
## [1.13.0] - 2025-12-23
|
|
10
25
|
|
|
11
26
|
### Added
|
|
12
|
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
- Added context `merge` alias for `merge!`
|
|
27
|
+
- Add rollback tracking and logging for task execution
|
|
28
|
+
- Add `dry_run` execution option with inheritance support for nested tasks
|
|
29
|
+
- Add `Context#delete` alias for `Context#delete!`
|
|
30
|
+
- Add `Context#merge` alias for `Context#merge!`
|
|
17
31
|
|
|
18
32
|
## [1.12.0] - 2025-12-18
|
|
19
33
|
|
|
20
|
-
###
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
|
|
26
|
-
###
|
|
27
|
-
- Remove `handle_*` methods
|
|
28
|
-
- Optimize logging ancestor lookup
|
|
29
|
-
- Use chop instead of range for better string performance
|
|
30
|
-
- Update boolean coercion `TRUTHY` and `FALSEY` regexp to be case insensitive
|
|
31
|
-
- Improve YARD documentation with `yard-lint`
|
|
34
|
+
### Changed
|
|
35
|
+
- Optimize logging ancestor chain lookup performance
|
|
36
|
+
- Use `String#chop` instead of range indexing for improved string performance
|
|
37
|
+
- Make boolean coercion `TRUTHY` and `FALSEY` patterns case-insensitive
|
|
38
|
+
- Enhance YARD documentation using `yard-lint` validation
|
|
39
|
+
|
|
40
|
+
### Removed
|
|
41
|
+
- Remove `handle_*` callback methods in favor of `on(*states_or_statuses)` for flexible state handling
|
|
32
42
|
|
|
33
43
|
## [1.11.0] - 2025-11-08
|
|
34
44
|
|
|
35
|
-
###
|
|
36
|
-
-
|
|
37
|
-
- Update specs to use new `cmdx-rspec` matcher
|
|
45
|
+
### Changed
|
|
46
|
+
- Add conditional requirement support for attribute validation
|
|
47
|
+
- Update specs to use new `cmdx-rspec` matcher naming conventions
|
|
38
48
|
|
|
39
49
|
## [1.10.1] - 2025-11-06
|
|
40
50
|
|
|
41
51
|
### Added
|
|
42
|
-
-
|
|
43
|
-
- Added YARDoc documentation to docs site
|
|
52
|
+
- Add YARDoc documentation to documentation site
|
|
44
53
|
|
|
45
54
|
### Removed
|
|
46
|
-
-
|
|
55
|
+
- Remove unused `Executor#repeator` method
|
|
47
56
|
|
|
48
57
|
## [1.10.0] - 2025-10-26
|
|
49
58
|
|
|
50
59
|
### Added
|
|
51
|
-
-
|
|
52
|
-
-
|
|
53
|
-
- Added Stoplight circuit breaker integration example
|
|
60
|
+
- Add `rollback` capability to undo operations based on status
|
|
61
|
+
- Add retry mechanism documentation
|
|
54
62
|
|
|
55
|
-
###
|
|
56
|
-
-
|
|
63
|
+
### Changed
|
|
64
|
+
- Extend `retry_jitter` option to accept symbols, procs, and callable objects
|
|
57
65
|
|
|
58
66
|
## [1.9.1] - 2025-10-22
|
|
59
67
|
|
|
60
68
|
### Added
|
|
61
|
-
-
|
|
62
|
-
-
|
|
69
|
+
- Add RBS inline type signatures
|
|
70
|
+
- Add YARDocs for `attr_reader` and `attr_accessor` methods
|
|
63
71
|
|
|
64
72
|
## [1.9.0] - 2025-10-21
|
|
65
73
|
|
|
66
74
|
### Added
|
|
67
|
-
-
|
|
68
|
-
-
|
|
69
|
-
-
|
|
70
|
-
-
|
|
71
|
-
-
|
|
72
|
-
-
|
|
75
|
+
- Add `transform` option for attribute value transformations
|
|
76
|
+
- Add optional failure backtrace output
|
|
77
|
+
- Add exception handling for non-bang execution methods
|
|
78
|
+
- Add automatic retry mechanism for execution durability
|
|
79
|
+
- Add `to_h` hash coercion support
|
|
80
|
+
- Add MkDocs configuration with Material theme
|
|
73
81
|
|
|
74
82
|
### Changed
|
|
75
|
-
-
|
|
76
|
-
-
|
|
77
|
-
-
|
|
78
|
-
-
|
|
83
|
+
- Improve task settings initialization performance
|
|
84
|
+
- Improve exception error message clarity
|
|
85
|
+
- Improve parent settings inheritance behavior
|
|
86
|
+
- Clean halt backtrace frames for better readability
|
|
79
87
|
|
|
80
88
|
### Removed
|
|
81
|
-
-
|
|
82
|
-
-
|
|
83
|
-
-
|
|
84
|
-
-
|
|
89
|
+
- Remove `Freezer` module; consolidate logic into `Executor#freeze_execution!`
|
|
90
|
+
- Remove `task` parameter from callback method signatures
|
|
91
|
+
- Remove `task` and `workflow` arguments from conditional checks
|
|
92
|
+
- Remove chain persistence after execution in specs
|
|
85
93
|
|
|
86
94
|
## [1.8.0] - 2025-09-22
|
|
87
95
|
|
|
88
96
|
### Changed
|
|
89
|
-
-
|
|
90
|
-
-
|
|
91
|
-
-
|
|
92
|
-
-
|
|
93
|
-
-
|
|
97
|
+
- Generalize locale values for `invalid` and `unspecified` faults
|
|
98
|
+
- Nest attribute error messages under `error` key in metadata
|
|
99
|
+
- Reorder Logstash formatter keys for consistency
|
|
100
|
+
- Improve error messaging for duplicate item definitions
|
|
101
|
+
- Return empty hash `{}` for `nil` hash coercion
|
|
94
102
|
|
|
95
103
|
## [1.7.5] - 2025-09-10
|
|
96
104
|
|
|
97
105
|
### Added
|
|
98
|
-
-
|
|
99
|
-
-
|
|
100
|
-
-
|
|
101
|
-
-
|
|
106
|
+
- Add `Context#fetch_or_store` method for atomic get-or-set operations
|
|
107
|
+
- Add `Result#ctx` alias for `Result#context`
|
|
108
|
+
- Add `Result#ok?` alias for `Result#good?`
|
|
109
|
+
- Add result deconstruction support for pattern matching
|
|
102
110
|
|
|
103
111
|
## [1.7.4] - 2025-09-03
|
|
104
112
|
|
|
105
113
|
### Added
|
|
106
|
-
-
|
|
107
|
-
-
|
|
114
|
+
- Add errors delegation from result object
|
|
115
|
+
- Add `Errors#full_messages` and `Errors#to_hash` methods
|
|
108
116
|
|
|
109
117
|
## [1.7.3] - 2025-09-03
|
|
110
118
|
|
|
111
119
|
### Changed
|
|
112
|
-
-
|
|
113
|
-
-
|
|
120
|
+
- Use generic validation reason values
|
|
121
|
+
- Move validation full message to `:full_message` key in metadata
|
|
114
122
|
|
|
115
123
|
## [1.7.2] - 2025-09-03
|
|
116
124
|
|
|
117
125
|
### Changed
|
|
118
|
-
-
|
|
126
|
+
- Set correlation ID before proceeding to subsequent execution steps
|
|
119
127
|
|
|
120
128
|
## [1.7.1] - 2025-08-26
|
|
121
129
|
|
|
122
130
|
### Added
|
|
123
|
-
-
|
|
131
|
+
- Add block yielding support to `execute` and `execute!` methods
|
|
124
132
|
|
|
125
133
|
## [1.7.0] - 2025-08-25
|
|
126
134
|
|
|
127
135
|
### Added
|
|
128
|
-
-
|
|
136
|
+
- Add workflow generator
|
|
129
137
|
|
|
130
138
|
### Changed
|
|
131
|
-
-
|
|
132
|
-
-
|
|
139
|
+
- Integrate `cmdx-parallel` functionality into core
|
|
140
|
+
- Integrate `cmdx-i18n` functionality into core
|
|
133
141
|
|
|
134
142
|
## [1.6.2] - 2025-08-24
|
|
135
143
|
|
|
136
144
|
### Changed
|
|
137
|
-
-
|
|
138
|
-
-
|
|
145
|
+
- Prefix railtie I18n with `::` for `CMDx::I18n` compatibility
|
|
146
|
+
- Switch to `cmdx-rspec` for matcher support
|
|
139
147
|
|
|
140
148
|
## [1.6.1] - 2025-08-23
|
|
141
149
|
|
|
142
150
|
### Changed
|
|
143
|
-
-
|
|
144
|
-
-
|
|
151
|
+
- Log task results before freezing execution state
|
|
152
|
+
- Rename `execute_tasks_sequentially` to `execute_tasks_in_sequence`
|
|
145
153
|
|
|
146
154
|
## [1.6.0] - 2025-08-22
|
|
147
155
|
|
|
148
156
|
### Added
|
|
149
|
-
-
|
|
157
|
+
- Add workflow task `:breakpoints` support
|
|
150
158
|
|
|
151
159
|
### Changed
|
|
152
|
-
-
|
|
153
|
-
-
|
|
160
|
+
- Rename `Worker` class to `Executor`
|
|
161
|
+
- Extract workflow execution logic into `Pipeline` class
|
|
154
162
|
|
|
155
163
|
## [1.5.2] - 2025-08-22
|
|
156
164
|
|
|
157
165
|
### Changed
|
|
158
|
-
-
|
|
166
|
+
- Rename workflow `execution_groups` attribute to `pipeline`
|
|
159
167
|
|
|
160
168
|
## [1.5.1] - 2025-08-21
|
|
161
169
|
|
|
162
170
|
### Changed
|
|
163
|
-
-
|
|
164
|
-
-
|
|
165
|
-
-
|
|
171
|
+
- Prefix locale I18n with `::` for `CMDx::I18n` compatibility
|
|
172
|
+
- Add safe navigation to length and numeric validators
|
|
173
|
+
- Fix railtie file path to reference correct directory
|
|
166
174
|
|
|
167
175
|
## [1.5.0] - 2025-08-21
|
|
168
176
|
|
|
169
177
|
### Changed
|
|
170
|
-
- **BREAKING**:
|
|
178
|
+
- **BREAKING**: Complete architecture redesign for improved clarity, transparency, and performance
|
|
171
179
|
|
|
172
180
|
## [1.1.2] - 2025-07-20
|
|
173
181
|
|
|
174
182
|
### Changed
|
|
175
|
-
-
|
|
183
|
+
- See git tags for changes between versions 0.1.0 and 1.1.2
|
|
176
184
|
|
|
177
185
|
## [0.1.0] - 2025-03-07
|
|
178
186
|
|
data/LICENSE.txt
CHANGED
|
@@ -1,21 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
Copyright (c) Drexed
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in
|
|
13
|
-
all copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
-
THE SOFTWARE.
|
|
3
|
+
CMDx is an Open Source project licensed under the terms of the LGPLv3 license.
|
|
4
|
+
Please see <http://www.gnu.org/licenses/lgpl-3.0.html> for license text.
|
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<img src="./src/cmdx-light-logo.png#gh-light-mode-only" width="200" alt="CMDx Logo">
|
|
3
|
-
<img src="./src/cmdx-dark-logo.png#gh-dark-mode-only" width="200" alt="CMDx Logo">
|
|
2
|
+
<img src="./src/cmdx-light-logo.png#gh-light-mode-only" width="200" alt="CMDx Light Logo">
|
|
3
|
+
<img src="./src/cmdx-dark-logo.png#gh-dark-mode-only" width="200" alt="CMDx Dark Logo">
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
<img alt="Version" src="https://img.shields.io/gem/v/cmdx">
|
|
12
12
|
<img alt="Build" src="https://github.com/drexed/cmdx/actions/workflows/ci.yml/badge.svg">
|
|
13
|
-
<img alt="License" src="https://img.shields.io/
|
|
13
|
+
<img alt="License" src="https://img.shields.io/badge/license-LGPL%20v3-blue.svg">
|
|
14
14
|
</div>
|
|
15
15
|
|
|
16
16
|
# CMDx
|
|
@@ -18,13 +18,14 @@
|
|
|
18
18
|
Say goodbye to messy service objects. CMDx helps you design business logic with clarity and consistency—build faster, debug easier, and ship with confidence.
|
|
19
19
|
|
|
20
20
|
> [!NOTE]
|
|
21
|
-
> Documentation reflects the latest code on `main`. For version-specific documentation, please refer to the `docs/` directory within that version's tag.
|
|
21
|
+
> [Documentation](https://drexed.github.io/cmdx/getting_started/) reflects the latest code on `main`. For version-specific documentation, please refer to the `docs/` directory within that version's tag.
|
|
22
22
|
|
|
23
23
|
## Requirements
|
|
24
24
|
|
|
25
|
-
- Ruby: MRI 3.1+ or JRuby 9.4
|
|
25
|
+
- Ruby: MRI 3.1+ or JRuby 9.4+
|
|
26
|
+
- Dependencies: None
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
Rails support is built-in, but it's framework-agnostic at its core.
|
|
28
29
|
|
|
29
30
|
## Installation
|
|
30
31
|
|
|
@@ -125,4 +126,4 @@ Bug reports and pull requests are welcome at <https://github.com/drexed/cmdx>. W
|
|
|
125
126
|
|
|
126
127
|
## License
|
|
127
128
|
|
|
128
|
-
The gem is available as open source under the terms of the [
|
|
129
|
+
The gem is available as open source under the terms of the [LGPLv3 License](https://www.gnu.org/licenses/lgpl-3.0.html).
|
data/lib/cmdx/attribute.rb
CHANGED
|
@@ -235,6 +235,23 @@ module CMDx
|
|
|
235
235
|
end
|
|
236
236
|
end
|
|
237
237
|
|
|
238
|
+
# @return [Hash] A hash representation of the attribute
|
|
239
|
+
#
|
|
240
|
+
# @example
|
|
241
|
+
# attribute.to_h # => { name: :user_id, method_name: :user_id, required: true, types: [:integer], options: {}, children: [] }
|
|
242
|
+
#
|
|
243
|
+
# @rbs () -> Hash[Symbol, untyped]
|
|
244
|
+
def to_h
|
|
245
|
+
{
|
|
246
|
+
name: name,
|
|
247
|
+
method_name: method_name,
|
|
248
|
+
required: required?,
|
|
249
|
+
types: types,
|
|
250
|
+
options: options.except(:if, :unless),
|
|
251
|
+
children: children.map(&:to_h)
|
|
252
|
+
}
|
|
253
|
+
end
|
|
254
|
+
|
|
238
255
|
private
|
|
239
256
|
|
|
240
257
|
# Creates nested attributes as children of this attribute.
|
|
@@ -312,11 +329,10 @@ module CMDx
|
|
|
312
329
|
attribute_value.generate
|
|
313
330
|
attribute_value.validate
|
|
314
331
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
RUBY
|
|
332
|
+
name_of_method = method_name
|
|
333
|
+
task.define_singleton_method(name_of_method) do
|
|
334
|
+
attributes[name_of_method]
|
|
335
|
+
end
|
|
320
336
|
end
|
|
321
337
|
|
|
322
338
|
end
|
data/lib/cmdx/context.rb
CHANGED
|
@@ -185,6 +185,22 @@ module CMDx
|
|
|
185
185
|
end
|
|
186
186
|
alias delete delete!
|
|
187
187
|
|
|
188
|
+
# Clears all key-value pairs from the context.
|
|
189
|
+
#
|
|
190
|
+
# @return [Context] self for method chaining
|
|
191
|
+
#
|
|
192
|
+
# @example
|
|
193
|
+
# context = Context.new(name: "John")
|
|
194
|
+
# context.clear!
|
|
195
|
+
# context.to_h # => {}
|
|
196
|
+
#
|
|
197
|
+
# @rbs () -> self
|
|
198
|
+
def clear!
|
|
199
|
+
table.clear
|
|
200
|
+
self
|
|
201
|
+
end
|
|
202
|
+
alias clear clear!
|
|
203
|
+
|
|
188
204
|
# Compares this context with another object for equality.
|
|
189
205
|
#
|
|
190
206
|
# @param other [Object] the object to compare with
|
data/lib/cmdx/executor.rb
CHANGED
|
@@ -138,17 +138,17 @@ module CMDx
|
|
|
138
138
|
#
|
|
139
139
|
# @rbs (Exception exception) -> bool
|
|
140
140
|
def retry_execution?(exception)
|
|
141
|
-
available_retries = (task.class.settings[:retries] || 0)
|
|
141
|
+
available_retries = Integer(task.class.settings[:retries] || 0)
|
|
142
142
|
return false unless available_retries.positive?
|
|
143
143
|
|
|
144
|
-
|
|
145
|
-
remaining_retries = available_retries -
|
|
144
|
+
current_retry = result.retries
|
|
145
|
+
remaining_retries = available_retries - current_retry
|
|
146
146
|
return false unless remaining_retries.positive?
|
|
147
147
|
|
|
148
148
|
exceptions = Array(task.class.settings[:retry_on] || StandardError)
|
|
149
149
|
return false unless exceptions.any? { |e| exception.class <= e }
|
|
150
150
|
|
|
151
|
-
result.
|
|
151
|
+
result.retries += 1
|
|
152
152
|
|
|
153
153
|
task.logger.warn do
|
|
154
154
|
reason = "[#{exception.class}] #{exception.message}"
|
|
@@ -158,13 +158,13 @@ module CMDx
|
|
|
158
158
|
jitter = task.class.settings[:retry_jitter]
|
|
159
159
|
jitter =
|
|
160
160
|
if jitter.is_a?(Symbol)
|
|
161
|
-
task.send(jitter,
|
|
161
|
+
task.send(jitter, current_retry)
|
|
162
162
|
elsif jitter.is_a?(Proc)
|
|
163
|
-
task.instance_exec(
|
|
163
|
+
task.instance_exec(current_retry, &jitter)
|
|
164
164
|
elsif jitter.respond_to?(:call)
|
|
165
|
-
jitter.call(task,
|
|
165
|
+
jitter.call(task, current_retry)
|
|
166
166
|
else
|
|
167
|
-
jitter.to_f *
|
|
167
|
+
jitter.to_f * current_retry
|
|
168
168
|
end
|
|
169
169
|
|
|
170
170
|
sleep(jitter) if jitter.positive?
|
|
@@ -320,7 +320,7 @@ module CMDx
|
|
|
320
320
|
statuses = Array(statuses).map(&:to_s).uniq
|
|
321
321
|
return unless statuses.include?(result.status)
|
|
322
322
|
|
|
323
|
-
result.rolled_back
|
|
323
|
+
result.rolled_back = true
|
|
324
324
|
task.rollback
|
|
325
325
|
end
|
|
326
326
|
|
data/lib/cmdx/result.rb
CHANGED
|
@@ -70,7 +70,7 @@ module CMDx
|
|
|
70
70
|
# @return [Hash{Symbol => Object}] Metadata hash
|
|
71
71
|
#
|
|
72
72
|
# @example
|
|
73
|
-
# result.metadata # => { duration: 1.5,
|
|
73
|
+
# result.metadata # => { duration: 1.5, code: 200, message: "Success" }
|
|
74
74
|
#
|
|
75
75
|
# @rbs @metadata: Hash[Symbol, untyped]
|
|
76
76
|
attr_reader :metadata
|
|
@@ -95,6 +95,26 @@ module CMDx
|
|
|
95
95
|
# @rbs @cause: (Exception | nil)
|
|
96
96
|
attr_reader :cause
|
|
97
97
|
|
|
98
|
+
# Returns the number of retries attempted.
|
|
99
|
+
#
|
|
100
|
+
# @return [Integer] The number of retries attempted
|
|
101
|
+
#
|
|
102
|
+
# @example
|
|
103
|
+
# result.retries # => 2
|
|
104
|
+
#
|
|
105
|
+
# @rbs @retries: Integer
|
|
106
|
+
attr_accessor :retries
|
|
107
|
+
|
|
108
|
+
# Returns whether the result has been rolled back.
|
|
109
|
+
#
|
|
110
|
+
# @return [Boolean] Whether the result has been rolled back
|
|
111
|
+
#
|
|
112
|
+
# @example
|
|
113
|
+
# result.rolled_back? # => true
|
|
114
|
+
#
|
|
115
|
+
# @rbs @rolled_back: bool
|
|
116
|
+
attr_accessor :rolled_back
|
|
117
|
+
|
|
98
118
|
def_delegators :task, :context, :chain, :errors, :dry_run?
|
|
99
119
|
alias ctx context
|
|
100
120
|
|
|
@@ -118,6 +138,7 @@ module CMDx
|
|
|
118
138
|
@metadata = {}
|
|
119
139
|
@reason = nil
|
|
120
140
|
@cause = nil
|
|
141
|
+
@retries = 0
|
|
121
142
|
@rolled_back = false
|
|
122
143
|
end
|
|
123
144
|
|
|
@@ -420,15 +441,14 @@ module CMDx
|
|
|
420
441
|
failed? && !caused_failure?
|
|
421
442
|
end
|
|
422
443
|
|
|
423
|
-
# @return [
|
|
444
|
+
# @return [Boolean] Whether the result has been retried
|
|
424
445
|
#
|
|
425
446
|
# @example
|
|
426
|
-
# result.
|
|
427
|
-
# result.rolled_back? # => true
|
|
447
|
+
# result.retried? # => true
|
|
428
448
|
#
|
|
429
|
-
# @rbs () ->
|
|
430
|
-
def
|
|
431
|
-
|
|
449
|
+
# @rbs () -> bool
|
|
450
|
+
def retried?
|
|
451
|
+
retries.positive?
|
|
432
452
|
end
|
|
433
453
|
|
|
434
454
|
# @return [Boolean] Whether the result has been rolled back
|
data/lib/cmdx/task.rb
CHANGED
|
@@ -217,6 +217,25 @@ module CMDx
|
|
|
217
217
|
end
|
|
218
218
|
alias remove_attribute remove_attributes
|
|
219
219
|
|
|
220
|
+
# @return [Hash] Hash of attribute names to their configurations
|
|
221
|
+
#
|
|
222
|
+
# @example
|
|
223
|
+
# MyTask.attributes_schema #=> {
|
|
224
|
+
# user_id: { name: :user_id, method_name: :user_id, required: true, types: [:integer], options: {}, children: [] },
|
|
225
|
+
# email: { name: :email, method_name: :email, required: false, types: [:string], options: { default: nil }, children: [] },
|
|
226
|
+
# profile: { name: :profile, method_name: :profile, required: false, types: [:hash], options: {}, children: [
|
|
227
|
+
# { name: :bio, method_name: :bio, required: false, types: [:string], options: {}, children: [] },
|
|
228
|
+
# { name: :name, method_name: :name, required: true, types: [:string], options: {}, children: [] }
|
|
229
|
+
# ] }
|
|
230
|
+
# }
|
|
231
|
+
#
|
|
232
|
+
# @rbs () -> Hash[Symbol, Hash[Symbol, untyped]]
|
|
233
|
+
def attributes_schema
|
|
234
|
+
Array(settings[:attributes]).each_with_object({}) do |attr, schema|
|
|
235
|
+
schema[attr.method_name] = attr.to_h
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
|
|
220
239
|
CallbackRegistry::TYPES.each do |callback|
|
|
221
240
|
# @param callables [Array] Callable objects to register as callbacks
|
|
222
241
|
# @param options [Hash] Options for the callback registration
|