cmdx 1.10.0 β 1.10.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/.yardopts +7 -0
- data/CHANGELOG.md +9 -0
- data/Rakefile +21 -0
- data/docs/configuration.md +314 -0
- data/docs/getting_started.md +37 -300
- data/docs/index.md +4 -2
- data/docs/retries.md +1 -1
- data/docs/stylesheets/extra.css +26 -26
- data/docs/tips_and_tricks.md +2 -1
- data/examples/sidekiq_async_execution.md +29 -0
- data/lib/cmdx/executor.rb +0 -7
- data/lib/cmdx/version.rb +1 -1
- data/mkdocs.yml +65 -19
- metadata +18 -2
- data/LLM.md +0 -3727
data/docs/getting_started.md
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
CMDx is a Ruby framework for building maintainable, observable business logic through composable command objects. It brings structure, consistency, and powerful developer tools to your business processes.
|
|
4
4
|
|
|
5
|
-
**Common challenges
|
|
5
|
+
**Common challenges:**
|
|
6
6
|
|
|
7
7
|
- Inconsistent service object patterns across your codebase
|
|
8
|
-
-
|
|
8
|
+
- Black boxes make debugging a nightmare
|
|
9
9
|
- Fragile error handling erodes confidence
|
|
10
10
|
|
|
11
11
|
**What you get:**
|
|
@@ -17,343 +17,80 @@ CMDx is a Ruby framework for building maintainable, observable business logic th
|
|
|
17
17
|
- Attribute validation with type coercions
|
|
18
18
|
- Sensible defaults and developer-friendly APIs
|
|
19
19
|
|
|
20
|
-
## The CERO Pattern
|
|
21
|
-
|
|
22
|
-
CMDx embraces the Compose, Execute, React, Observe (CERO) patternβa simple yet powerful approach to building reliable business logic.
|
|
23
|
-
|
|
24
|
-
π§© **Compose** β Define small, focused tasks with typed attributes and validations
|
|
25
|
-
|
|
26
|
-
β‘ **Execute** β Run tasks with clear outcomes and pluggable behaviors
|
|
27
|
-
|
|
28
|
-
π **React** β Adapt to outcomes by chaining follow-up tasks or handling faults
|
|
29
|
-
|
|
30
|
-
π **Observe** β Capture structured logs and execution chains for debugging
|
|
31
|
-
|
|
32
20
|
## Installation
|
|
33
21
|
|
|
34
22
|
Add CMDx to your Gemfile:
|
|
35
23
|
|
|
36
|
-
```
|
|
37
|
-
gem
|
|
38
|
-
```
|
|
24
|
+
```sh
|
|
25
|
+
gem install cmdx
|
|
39
26
|
|
|
40
|
-
|
|
27
|
+
# - or -
|
|
41
28
|
|
|
42
|
-
|
|
43
|
-
rails generate cmdx:install
|
|
29
|
+
bundle add cmdx
|
|
44
30
|
```
|
|
45
31
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
## Configuration Hierarchy
|
|
49
|
-
|
|
50
|
-
CMDx uses a straightforward two-tier configuration system:
|
|
51
|
-
|
|
52
|
-
1. **Global Configuration** β Framework-wide defaults
|
|
53
|
-
2. **Task Settings** β Class-level overrides using `settings`
|
|
54
|
-
|
|
55
|
-
!!! warning "Important"
|
|
56
|
-
|
|
57
|
-
Task settings take precedence over global config. Settings are inherited from parent classes and can be overridden in subclasses.
|
|
58
|
-
|
|
59
|
-
## Global Configuration
|
|
60
|
-
|
|
61
|
-
Configure framework-wide defaults that apply to all tasks. These settings come with sensible defaults out of the box.
|
|
62
|
-
|
|
63
|
-
### Breakpoints
|
|
64
|
-
|
|
65
|
-
Control when `execute!` raises a `CMDx::Fault` based on task status.
|
|
66
|
-
|
|
67
|
-
```ruby
|
|
68
|
-
CMDx.configure do |config|
|
|
69
|
-
config.task_breakpoints = "failed" # String or Array[String]
|
|
70
|
-
end
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
For workflows, configure which statuses halt the execution pipeline:
|
|
74
|
-
|
|
75
|
-
```ruby
|
|
76
|
-
CMDx.configure do |config|
|
|
77
|
-
config.workflow_breakpoints = ["skipped", "failed"]
|
|
78
|
-
end
|
|
79
|
-
```
|
|
32
|
+
## Configuration
|
|
80
33
|
|
|
81
|
-
|
|
34
|
+
For Rails applications, run the following command to generate a global configuration file in `config/initializers/cmdx.rb`.
|
|
82
35
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
```ruby
|
|
86
|
-
CMDx.configure do |config|
|
|
87
|
-
config.rollback_on = ["failed"] # String or Array[String]
|
|
88
|
-
end
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
### Backtraces
|
|
92
|
-
|
|
93
|
-
Enable detailed backtraces for non-fault exceptions to improve debugging. Optionally clean up stack traces to remove framework noise.
|
|
94
|
-
|
|
95
|
-
!!! note
|
|
96
|
-
|
|
97
|
-
In Rails environments, `backtrace_cleaner` defaults to `Rails.backtrace_cleaner.clean`.
|
|
98
|
-
|
|
99
|
-
```ruby
|
|
100
|
-
CMDx.configure do |config|
|
|
101
|
-
# Truthy
|
|
102
|
-
config.backtrace = true
|
|
103
|
-
|
|
104
|
-
# Via callable (must respond to `call(backtrace)`)
|
|
105
|
-
config.backtrace_cleaner = AdvanceCleaner.new
|
|
106
|
-
|
|
107
|
-
# Via proc or lambda
|
|
108
|
-
config.backtrace_cleaner = ->(backtrace) { backtrace[0..5] }
|
|
109
|
-
end
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
### Exception Handlers
|
|
113
|
-
|
|
114
|
-
Register handlers that run when non-fault exceptions occur.
|
|
115
|
-
|
|
116
|
-
!!! tip
|
|
117
|
-
|
|
118
|
-
Use exception handlers to send errors to your APM of choice.
|
|
119
|
-
|
|
120
|
-
```ruby
|
|
121
|
-
CMDx.configure do |config|
|
|
122
|
-
# Via callable (must respond to `call(task, exception)`)
|
|
123
|
-
config.exception_handler = NewRelicReporter
|
|
124
|
-
|
|
125
|
-
# Via proc or lambda
|
|
126
|
-
config.exception_handler = proc do |task, exception|
|
|
127
|
-
APMService.report(exception, extra_data: { task: task.name, id: task.id })
|
|
128
|
-
end
|
|
129
|
-
end
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
### Logging
|
|
133
|
-
|
|
134
|
-
```ruby
|
|
135
|
-
CMDx.configure do |config|
|
|
136
|
-
config.logger = CustomLogger.new($stdout)
|
|
137
|
-
end
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
### Middlewares
|
|
141
|
-
|
|
142
|
-
See the [Middlewares](middlewares.md#declarations) docs for task level configurations.
|
|
143
|
-
|
|
144
|
-
```ruby
|
|
145
|
-
CMDx.configure do |config|
|
|
146
|
-
# Via callable (must respond to `call(task, options)`)
|
|
147
|
-
config.middlewares.register CMDx::Middlewares::Timeout
|
|
148
|
-
|
|
149
|
-
# Via proc or lambda
|
|
150
|
-
config.middlewares.register proc { |task, options|
|
|
151
|
-
start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
152
|
-
result = yield
|
|
153
|
-
end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
154
|
-
Rails.logger.debug { "task completed in #{((end_time - start_time) * 1000).round(2)}ms" }
|
|
155
|
-
result
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
# With options
|
|
159
|
-
config.middlewares.register AuditTrailMiddleware, service_name: "document_processor"
|
|
160
|
-
|
|
161
|
-
# Remove middleware
|
|
162
|
-
config.middlewares.deregister CMDx::Middlewares::Timeout
|
|
163
|
-
end
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
!!! note
|
|
167
|
-
|
|
168
|
-
Middlewares are executed in registration order. Each middleware wraps the next, creating an execution chain around task logic.
|
|
169
|
-
|
|
170
|
-
### Callbacks
|
|
171
|
-
|
|
172
|
-
See the [Callbacks](callbacks.md#declarations) docs for task level configurations.
|
|
173
|
-
|
|
174
|
-
```ruby
|
|
175
|
-
CMDx.configure do |config|
|
|
176
|
-
# Via method
|
|
177
|
-
config.callbacks.register :before_execution, :initialize_user_session
|
|
178
|
-
|
|
179
|
-
# Via callable (must respond to `call(task)`)
|
|
180
|
-
config.callbacks.register :on_success, LogUserActivity
|
|
181
|
-
|
|
182
|
-
# Via proc or lambda
|
|
183
|
-
config.callbacks.register :on_complete, proc { |task|
|
|
184
|
-
execution_time = task.metadata[:runtime]
|
|
185
|
-
Metrics.timer("task.execution_time", execution_time, tags: ["task:#{task.class.name.underscore}"])
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
# With options
|
|
189
|
-
config.callbacks.register :on_failure, :send_alert_notification, if: :critical_task?
|
|
190
|
-
|
|
191
|
-
# Remove callback
|
|
192
|
-
config.callbacks.deregister :on_success, LogUserActivity
|
|
193
|
-
end
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
### Coercions
|
|
197
|
-
|
|
198
|
-
See the [Attributes - Coercions](attributes/coercions.md#declarations) docs for task level configurations.
|
|
199
|
-
|
|
200
|
-
```ruby
|
|
201
|
-
CMDx.configure do |config|
|
|
202
|
-
# Via callable (must respond to `call(value, options)`)
|
|
203
|
-
config.coercions.register :currency, CurrencyCoercion
|
|
204
|
-
|
|
205
|
-
# Via method (must match signature `def coordinates_coercion(value, options)`)
|
|
206
|
-
config.coercions.register :coordinates, :coordinates_coercion
|
|
207
|
-
|
|
208
|
-
# Via proc or lambda
|
|
209
|
-
config.coercions.register :tag_list, proc { |value, options|
|
|
210
|
-
delimiter = options[:delimiter] || ','
|
|
211
|
-
max_tags = options[:max_tags] || 50
|
|
212
|
-
|
|
213
|
-
tags = value.to_s.split(delimiter).map(&:strip).reject(&:empty?)
|
|
214
|
-
tags.first(max_tags)
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
# Remove coercion
|
|
218
|
-
config.coercions.deregister :currency
|
|
219
|
-
end
|
|
36
|
+
```bash
|
|
37
|
+
rails generate cmdx:install
|
|
220
38
|
```
|
|
221
39
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
See the [Attributes - Validations](attributes/validations.md#declarations) docs for task level configurations.
|
|
225
|
-
|
|
226
|
-
```ruby
|
|
227
|
-
CMDx.configure do |config|
|
|
228
|
-
# Via callable (must respond to `call(value, options)`)
|
|
229
|
-
config.validators.register :username, UsernameValidator
|
|
230
|
-
|
|
231
|
-
# Via method (must match signature `def url_validator(value, options)`)
|
|
232
|
-
config.validators.register :url, :url_validator
|
|
40
|
+
If not using Rails, manually copy the [configuration file](https://github.com/drexed/cmdx/blob/main/lib/generators/cmdx/templates/install.rb).
|
|
233
41
|
|
|
234
|
-
|
|
235
|
-
config.validators.register :access_token, proc { |value, options|
|
|
236
|
-
expected_prefix = options[:prefix] || "tok_"
|
|
237
|
-
minimum_length = options[:min_length] || 40
|
|
238
|
-
|
|
239
|
-
value.start_with?(expected_prefix) && value.length >= minimum_length
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
# Remove validator
|
|
243
|
-
config.validators.deregister :username
|
|
244
|
-
end
|
|
245
|
-
```
|
|
42
|
+
## The CERO Pattern
|
|
246
43
|
|
|
247
|
-
|
|
44
|
+
CMDx embraces the Compose, Execute, React, Observe (CERO, pronounced "zero") patternβa simple yet powerful approach to building reliable business logic.
|
|
248
45
|
|
|
249
|
-
###
|
|
46
|
+
### Compose
|
|
250
47
|
|
|
251
|
-
|
|
48
|
+
Build reusable, single-responsibility tasks with typed attributes, validation, and callbacks. Tasks can be chained together in workflows to create complex business processes from simple building blocks.
|
|
252
49
|
|
|
253
50
|
```ruby
|
|
254
|
-
class
|
|
255
|
-
settings(
|
|
256
|
-
# Global configuration overrides
|
|
257
|
-
task_breakpoints: ["failed"], # Breakpoint override
|
|
258
|
-
workflow_breakpoints: [], # Breakpoint override
|
|
259
|
-
backtrace: true, # Toggle backtrace
|
|
260
|
-
backtrace_cleaner: ->(bt) { bt[0..5] }, # Backtrace cleaner
|
|
261
|
-
logger: CustomLogger.new($stdout), # Custom logger
|
|
262
|
-
|
|
263
|
-
# Task configuration settings
|
|
264
|
-
breakpoints: ["failed"], # Contextual pointer for :task_breakpoints and :workflow_breakpoints
|
|
265
|
-
log_level: :info, # Log level override
|
|
266
|
-
log_formatter: CMDx::LogFormatters::Json.new # Log formatter override
|
|
267
|
-
tags: ["billing", "financial"], # Logging tags
|
|
268
|
-
deprecated: true, # Task deprecations
|
|
269
|
-
retries: 3, # Non-fault exception retries
|
|
270
|
-
retry_on: [External::ApiError], # List of exceptions to retry on
|
|
271
|
-
retry_jitter: 1, # Space between retry iteration, eg: current retry num + 1
|
|
272
|
-
rollback_on: ["failed", "skipped"], # Rollback on override
|
|
273
|
-
)
|
|
274
|
-
|
|
51
|
+
class AnalyzeMetrics < CMDx::Task
|
|
275
52
|
def work
|
|
276
53
|
# Your logic here...
|
|
277
54
|
end
|
|
278
55
|
end
|
|
279
56
|
```
|
|
280
57
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
Retries reuse the same context. By default, all `StandardError` exceptions (including faults) are retried unless you specify `retry_on` option for specific matches.
|
|
58
|
+
### Execute
|
|
284
59
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
Register or deregister middlewares, callbacks, coercions, and validators for specific tasks:
|
|
60
|
+
Invoke tasks with a consistent API that always returns a result object. Execution automatically handles validation, type coercion, error handling, and logging. Arguments are validated and coerced before your task logic runs.
|
|
288
61
|
|
|
289
62
|
```ruby
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
register :middleware, CMDx::Middlewares::Timeout
|
|
293
|
-
deregister :middleware, AuditTrailMiddleware
|
|
294
|
-
|
|
295
|
-
# Callbacks
|
|
296
|
-
register :callback, :on_complete, proc { |task|
|
|
297
|
-
runtime = task.metadata[:runtime]
|
|
298
|
-
Analytics.track("email_campaign.sent", runtime, tags: ["task:#{task.class.name}"])
|
|
299
|
-
}
|
|
300
|
-
deregister :callback, :before_execution, :initialize_user_session
|
|
301
|
-
|
|
302
|
-
# Coercions
|
|
303
|
-
register :coercion, :currency, CurrencyCoercion
|
|
304
|
-
deregister :coercion, :coordinates
|
|
305
|
-
|
|
306
|
-
# Validators
|
|
307
|
-
register :validator, :username, :username_validator
|
|
308
|
-
deregister :validator, :url
|
|
63
|
+
# Without args
|
|
64
|
+
result = AnalyzeMetrics.execute
|
|
309
65
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
end
|
|
313
|
-
end
|
|
66
|
+
# With args
|
|
67
|
+
result = AnalyzeMetrics.execute(model: "blackbox", "sensitivity" => 3)
|
|
314
68
|
```
|
|
315
69
|
|
|
316
|
-
|
|
70
|
+
### React
|
|
317
71
|
|
|
318
|
-
|
|
72
|
+
Every execution returns a result object with a clear outcome. Check the result's state (`success?`, `failed?`, `skipped?`) and access returned values, error messages, and metadata to make informed decisions.
|
|
319
73
|
|
|
320
74
|
```ruby
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
#
|
|
327
|
-
class ProcessUpload < CMDx::Task
|
|
328
|
-
settings(tags: ["files", "storage"])
|
|
329
|
-
|
|
330
|
-
def work
|
|
331
|
-
self.class.settings[:logger] #=> Global configuration value
|
|
332
|
-
self.class.settings[:tags] #=> Task configuration value => ["files", "storage"]
|
|
333
|
-
end
|
|
75
|
+
if result.success?
|
|
76
|
+
# Handle success
|
|
77
|
+
elsif result.skipped?
|
|
78
|
+
# Handle skipped
|
|
79
|
+
elsif result.failed?
|
|
80
|
+
# Handle failed
|
|
334
81
|
end
|
|
335
82
|
```
|
|
336
83
|
|
|
337
|
-
###
|
|
84
|
+
### Observe
|
|
338
85
|
|
|
339
|
-
|
|
86
|
+
Every task execution generates structured logs with execution chains, runtime metrics, and contextual metadata. Logs can be automatically correlated using chain IDs, making it easy to trace complex workflows and debug issues.
|
|
340
87
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
# Reset to framework defaults
|
|
345
|
-
CMDx.reset_configuration!
|
|
88
|
+
```log
|
|
89
|
+
I, [2022-07-17T18:42:37.000000 #3784] INFO -- CMDx:
|
|
90
|
+
index=1 chain_id="018c2b95-23j4-2kj3-32kj-3n4jk3n4jknf" type="Task" class="SendAnalyzedEmail" state="complete" status="success" metadata={runtime: 347}
|
|
346
91
|
|
|
347
|
-
#
|
|
348
|
-
|
|
349
|
-
CMDx.configuration.middlewares.registry #=> Empty registry
|
|
350
|
-
|
|
351
|
-
# Commonly used in test setup (RSpec example)
|
|
352
|
-
RSpec.configure do |config|
|
|
353
|
-
config.before(:each) do
|
|
354
|
-
CMDx.reset_configuration!
|
|
355
|
-
end
|
|
356
|
-
end
|
|
92
|
+
I, [2022-07-17T18:43:15.000000 #3784] INFO -- CMDx:
|
|
93
|
+
index=0 chain_id="018c2b95-b764-7615-a924-cc5b910ed1e5" type="Task" class="AnalyzeMetrics" state="complete" status="success" metadata={runtime: 187}
|
|
357
94
|
```
|
|
358
95
|
|
|
359
96
|
## Task Generator
|
data/docs/index.md
CHANGED
|
@@ -8,7 +8,7 @@ Build business logic that's powerful, predictable, and maintainable.
|
|
|
8
8
|
|
|
9
9
|
---
|
|
10
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.
|
|
11
|
+
Say goodbye to messy service objects. CMDx (pronounced "Command X") helps you design business logic with clarity and consistencyβbuild faster, debug easier, and ship with confidence.
|
|
12
12
|
|
|
13
13
|
!!! note
|
|
14
14
|
|
|
@@ -24,7 +24,9 @@ CMDx works with any Ruby framework. Rails support is built-in, but it's framewor
|
|
|
24
24
|
|
|
25
25
|
```sh
|
|
26
26
|
gem install cmdx
|
|
27
|
+
|
|
27
28
|
# - or -
|
|
29
|
+
|
|
28
30
|
bundle add cmdx
|
|
29
31
|
```
|
|
30
32
|
|
|
@@ -125,7 +127,7 @@ For backwards compatibility of certain functionality:
|
|
|
125
127
|
|
|
126
128
|
## Contributing
|
|
127
129
|
|
|
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).
|
|
130
|
+
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](https://github.com/drexed/cmdx/blob/main/CODE_OF_CONDUCT.md).
|
|
129
131
|
|
|
130
132
|
## License
|
|
131
133
|
|
data/docs/retries.md
CHANGED
|
@@ -17,7 +17,7 @@ class FetchExternalData < CMDx::Task
|
|
|
17
17
|
end
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
When an exception occurs during execution, CMDx automatically retries up to the configured limit.
|
|
20
|
+
When an exception occurs during execution, CMDx automatically retries up to the configured limit. Each retry attempt is logged at the `warn` level with retry metadata. If all retries are exhausted, the task fails with the original exception.
|
|
21
21
|
|
|
22
22
|
## Selective Retries
|
|
23
23
|
|
data/docs/stylesheets/extra.css
CHANGED
|
@@ -9,34 +9,34 @@
|
|
|
9
9
|
--md-accent-fg-color--transparent: hsla(#{hex2hsl(#fe1817)}, 0.1);
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
/*
|
|
12
|
+
/* GitHub High Contrast Light syntax highlighting */
|
|
13
13
|
[data-md-color-scheme="default"] {
|
|
14
|
-
--md-code-hl-color: #
|
|
15
|
-
--md-code-hl-keyword-color: #
|
|
16
|
-
--md-code-hl-string-color: #
|
|
17
|
-
--md-code-hl-name-color: #
|
|
18
|
-
--md-code-hl-function-color: #
|
|
19
|
-
--md-code-hl-number-color: #
|
|
20
|
-
--md-code-hl-constant-color: #
|
|
21
|
-
--md-code-hl-comment-color: #
|
|
22
|
-
--md-code-hl-operator-color: #
|
|
23
|
-
--md-code-hl-punctuation-color:#
|
|
24
|
-
--md-code-hl-variable-color: #
|
|
25
|
-
--md-code-hl-generic-color: #
|
|
14
|
+
--md-code-hl-color: #0e1116;
|
|
15
|
+
--md-code-hl-keyword-color: #a0095d;
|
|
16
|
+
--md-code-hl-string-color: #024c1a;
|
|
17
|
+
--md-code-hl-name-color: #622cbc;
|
|
18
|
+
--md-code-hl-function-color: #622cbc;
|
|
19
|
+
--md-code-hl-number-color: #0349b4;
|
|
20
|
+
--md-code-hl-constant-color: #702c00;
|
|
21
|
+
--md-code-hl-comment-color: #66707b;
|
|
22
|
+
--md-code-hl-operator-color: #a0095d;
|
|
23
|
+
--md-code-hl-punctuation-color:#0e1116;
|
|
24
|
+
--md-code-hl-variable-color: #702c00;
|
|
25
|
+
--md-code-hl-generic-color: #622cbc;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
/*
|
|
28
|
+
/* GitHub High Contrast Dark syntax highlighting */
|
|
29
29
|
[data-md-color-scheme="slate"] {
|
|
30
|
-
--md-code-hl-color: #
|
|
31
|
-
--md-code-hl-keyword-color: #
|
|
32
|
-
--md-code-hl-string-color: #
|
|
33
|
-
--md-code-hl-name-color: #
|
|
34
|
-
--md-code-hl-function-color: #
|
|
35
|
-
--md-code-hl-number-color: #
|
|
36
|
-
--md-code-hl-constant-color: #
|
|
37
|
-
--md-code-hl-comment-color: #
|
|
38
|
-
--md-code-hl-operator-color: #
|
|
39
|
-
--md-code-hl-punctuation-color:#
|
|
40
|
-
--md-code-hl-variable-color: #
|
|
41
|
-
--md-code-hl-generic-color: #
|
|
30
|
+
--md-code-hl-color: #f0f3f6;
|
|
31
|
+
--md-code-hl-keyword-color: #ff9492;
|
|
32
|
+
--md-code-hl-string-color: #addcff;
|
|
33
|
+
--md-code-hl-name-color: #dbb7ff;
|
|
34
|
+
--md-code-hl-function-color: #dbb7ff;
|
|
35
|
+
--md-code-hl-number-color: #91cbff;
|
|
36
|
+
--md-code-hl-constant-color: #ffb757;
|
|
37
|
+
--md-code-hl-comment-color: #9ea7b3;
|
|
38
|
+
--md-code-hl-operator-color: #ff9492;
|
|
39
|
+
--md-code-hl-punctuation-color:#f0f3f6;
|
|
40
|
+
--md-code-hl-variable-color: #ffb757;
|
|
41
|
+
--md-code-hl-generic-color: #dbb7ff;
|
|
42
42
|
}
|
data/docs/tips_and_tricks.md
CHANGED
|
@@ -145,8 +145,9 @@ class ConfigureCompany < CMDx::Task
|
|
|
145
145
|
end
|
|
146
146
|
```
|
|
147
147
|
|
|
148
|
-
##
|
|
148
|
+
## Useful Examples
|
|
149
149
|
|
|
150
150
|
- [Active Record Query Tagging](https://github.com/drexed/cmdx/blob/main/examples/active_record_query_tagging.md)
|
|
151
151
|
- [Paper Trail Whatdunnit](https://github.com/drexed/cmdx/blob/main/examples/paper_trail_whatdunnit.md)
|
|
152
|
+
- [Sidekiq Async Execution](https://github.com/drexed/cmdx/blob/main/examples/sidekiq_async_execution.md)
|
|
152
153
|
- [Stoplight Circuit Breaker](https://github.com/drexed/cmdx/blob/main/examples/stoplight_circuit_breaker.md)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Sidekiq Async Execute
|
|
2
|
+
|
|
3
|
+
Execute tasks asynchronously using Sidekiq without creating separate job classes.
|
|
4
|
+
|
|
5
|
+
<https://github.com/sidekiq/sidekiq>
|
|
6
|
+
|
|
7
|
+
### Setup
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
class MyTask < CMDx::Task
|
|
11
|
+
include Sidekiq::Job
|
|
12
|
+
|
|
13
|
+
def work
|
|
14
|
+
# Do work...
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Use execute! to trigger Sidekiq's retry logic on failures/exceptions.
|
|
18
|
+
def perform
|
|
19
|
+
self.class.execute!
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Usage
|
|
26
|
+
|
|
27
|
+
```ruby
|
|
28
|
+
MyTask.perform_async
|
|
29
|
+
```
|
data/lib/cmdx/executor.rb
CHANGED
|
@@ -197,13 +197,6 @@ module CMDx
|
|
|
197
197
|
|
|
198
198
|
private
|
|
199
199
|
|
|
200
|
-
# Lazy loaded repeator instance to handle retries.
|
|
201
|
-
#
|
|
202
|
-
# @rbs () -> untyped
|
|
203
|
-
def repeator
|
|
204
|
-
@repeator ||= Repeator.new(task)
|
|
205
|
-
end
|
|
206
|
-
|
|
207
200
|
# Performs pre-execution tasks including validation and attribute verification.
|
|
208
201
|
#
|
|
209
202
|
# @rbs () -> void
|