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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 633480d8f6383d5a872cfb8769fdfecc13e97879a90b0c1804144c0f93c7a26d
4
- data.tar.gz: 411eba7e1d4089cc1740de89cd1a1d5e05c1bf90235723019356fe827df8414c
3
+ metadata.gz: 8c19fc5a6ffdcec800571b94fb0d1ac43eb82ae771388ad69b2d5cd4293ef1b1
4
+ data.tar.gz: bee42f15d1cee3a969495d2267b702e311a6121ec684f1806d3dd82aff7b2bb1
5
5
  SHA512:
6
- metadata.gz: 8575a3967114e4140b62bd16f088160fcf350366aefd65ed49368fba9edf5ac4476d20f4e1f2f632e9b1fa2878501513c6580821d94a07c0de91ef092592f92f
7
- data.tar.gz: 351c404c1e6aa52ec21c09de5d4c8360777150534cddeb35d5e3ff750bacea7ad7886f74eddf26961d4dccf22a80acbe9727048f8753b0685295bb6f0c436fdc
6
+ metadata.gz: 934ebc5db4d532e7ab0254e34851910dba35ba86e0cf9f6b8462c24bdeab3cbd94ac588c791f67e31f188f0f09270489a168591cb4656e923811cd1cad9c883f
7
+ data.tar.gz: 69d7f39f7167bc045e86ae0f23c655dd8bebcb6e176963a981be17cd29e39025116ccb5f2fa2273a6d1b505eb76ec2fc846850b45d19c0f8423547931b95d383
data/.yardopts ADDED
@@ -0,0 +1,7 @@
1
+ --no-private
2
+ --output-dir
3
+ docs/api
4
+ --exclude
5
+ lib/generators/**/*.rb
6
+ lib/cmdx/railtie.rb
7
+ lib/**/*.rb
data/CHANGELOG.md CHANGED
@@ -6,6 +6,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
 
7
7
  ## [UNRELEASED]
8
8
 
9
+ ## [1.10.1] - 2025-11-06
10
+
11
+ ### Added
12
+ - Added Sidekiq async integration example
13
+ - Added YARDoc documentation to docs site
14
+
15
+ ### Removed
16
+ - Removed `Executor#repeator` method (never used)
17
+
9
18
  ## [1.10.0] - 2025-10-26
10
19
 
11
20
  ### Added
data/Rakefile CHANGED
@@ -9,4 +9,25 @@ require "rubocop/rake_task"
9
9
 
10
10
  RuboCop::RakeTask.new
11
11
 
12
+ desc "Generate YARD API documentation"
13
+ task :yard do
14
+ require "yard"
15
+ require "fileutils"
16
+
17
+ YARD::CLI::Yardoc.run(*File.readlines(".yardopts", chomp: true).reject(&:empty?))
18
+
19
+ api_dir = "docs/api"
20
+
21
+ # Remove unwanted files
22
+ FileUtils.rm_f("#{api_dir}/Cmdx_.html")
23
+ FileUtils.rm_f("#{api_dir}/top-level-namespace.html")
24
+ FileUtils.rm_f("#{api_dir}/CMDx/InstallGenerator.html")
25
+ FileUtils.rm_f("#{api_dir}/CMDx/LocaleGenerator.html")
26
+ FileUtils.rm_f("#{api_dir}/CMDx/TaskGenerator.html")
27
+ FileUtils.rm_f("#{api_dir}/CMDx/WorkflowGenerator.html")
28
+
29
+ # Make CMDx.html the default index
30
+ FileUtils.cp("#{api_dir}/CMDx.html", "#{api_dir}/index.html") if File.exist?("#{api_dir}/CMDx.html")
31
+ end
32
+
12
33
  task default: %i[spec rubocop]
@@ -0,0 +1,314 @@
1
+ # Configuration
2
+
3
+ Configure CMDx to customize framework behavior, register components, and control execution flow through global defaults with task-level overrides.
4
+
5
+ ## Configuration Hierarchy
6
+
7
+ CMDx uses a straightforward two-tier configuration system:
8
+
9
+ 1. **Global Configuration** — Framework-wide defaults
10
+ 2. **Task Settings** — Class-level overrides using `settings`
11
+
12
+ !!! warning "Important"
13
+
14
+ Task settings take precedence over global config. Settings are inherited from parent classes and can be overridden in subclasses.
15
+
16
+ ## Global Configuration
17
+
18
+ Configure framework-wide defaults that apply to all tasks. These settings come with sensible defaults out of the box.
19
+
20
+ ### Breakpoints
21
+
22
+ Control when `execute!` raises a `CMDx::Fault` based on task status.
23
+
24
+ ```ruby
25
+ CMDx.configure do |config|
26
+ config.task_breakpoints = "failed" # String or Array[String]
27
+ end
28
+ ```
29
+
30
+ For workflows, configure which statuses halt the execution pipeline:
31
+
32
+ ```ruby
33
+ CMDx.configure do |config|
34
+ config.workflow_breakpoints = ["skipped", "failed"]
35
+ end
36
+ ```
37
+
38
+ ### Rollback
39
+
40
+ Control when a `rollback` of task execution is called.
41
+
42
+ ```ruby
43
+ CMDx.configure do |config|
44
+ config.rollback_on = ["failed"] # String or Array[String]
45
+ end
46
+ ```
47
+
48
+ ### Backtraces
49
+
50
+ Enable detailed backtraces for non-fault exceptions to improve debugging. Optionally clean up stack traces to remove framework noise.
51
+
52
+ !!! note
53
+
54
+ In Rails environments, `backtrace_cleaner` defaults to `Rails.backtrace_cleaner.clean`.
55
+
56
+ ```ruby
57
+ CMDx.configure do |config|
58
+ # Truthy
59
+ config.backtrace = true
60
+
61
+ # Via callable (must respond to `call(backtrace)`)
62
+ config.backtrace_cleaner = AdvanceCleaner.new
63
+
64
+ # Via proc or lambda
65
+ config.backtrace_cleaner = ->(backtrace) { backtrace[0..5] }
66
+ end
67
+ ```
68
+
69
+ ### Exception Handlers
70
+
71
+ Register handlers that run when non-fault exceptions occur.
72
+
73
+ !!! tip
74
+
75
+ Use exception handlers to send errors to your APM of choice.
76
+
77
+ ```ruby
78
+ CMDx.configure do |config|
79
+ # Via callable (must respond to `call(task, exception)`)
80
+ config.exception_handler = NewRelicReporter
81
+
82
+ # Via proc or lambda
83
+ config.exception_handler = proc do |task, exception|
84
+ APMService.report(exception, extra_data: { task: task.name, id: task.id })
85
+ end
86
+ end
87
+ ```
88
+
89
+ ### Logging
90
+
91
+ ```ruby
92
+ CMDx.configure do |config|
93
+ config.logger = CustomLogger.new($stdout)
94
+ end
95
+ ```
96
+
97
+ ### Middlewares
98
+
99
+ See the [Middlewares](middlewares.md#declarations) docs for task level configurations.
100
+
101
+ ```ruby
102
+ CMDx.configure do |config|
103
+ # Via callable (must respond to `call(task, options)`)
104
+ config.middlewares.register CMDx::Middlewares::Timeout
105
+
106
+ # Via proc or lambda
107
+ config.middlewares.register proc { |task, options|
108
+ start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
109
+ result = yield
110
+ end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
111
+ Rails.logger.debug { "task completed in #{((end_time - start_time) * 1000).round(2)}ms" }
112
+ result
113
+ }
114
+
115
+ # With options
116
+ config.middlewares.register AuditTrailMiddleware, service_name: "document_processor"
117
+
118
+ # Remove middleware
119
+ config.middlewares.deregister CMDx::Middlewares::Timeout
120
+ end
121
+ ```
122
+
123
+ !!! note
124
+
125
+ Middlewares are executed in registration order. Each middleware wraps the next, creating an execution chain around task logic.
126
+
127
+ ### Callbacks
128
+
129
+ See the [Callbacks](callbacks.md#declarations) docs for task level configurations.
130
+
131
+ ```ruby
132
+ CMDx.configure do |config|
133
+ # Via method
134
+ config.callbacks.register :before_execution, :initialize_user_session
135
+
136
+ # Via callable (must respond to `call(task)`)
137
+ config.callbacks.register :on_success, LogUserActivity
138
+
139
+ # Via proc or lambda
140
+ config.callbacks.register :on_complete, proc { |task|
141
+ execution_time = task.metadata[:runtime]
142
+ Metrics.timer("task.execution_time", execution_time, tags: ["task:#{task.class.name.underscore}"])
143
+ }
144
+
145
+ # With options
146
+ config.callbacks.register :on_failure, :send_alert_notification, if: :critical_task?
147
+
148
+ # Remove callback
149
+ config.callbacks.deregister :on_success, LogUserActivity
150
+ end
151
+ ```
152
+
153
+ ### Coercions
154
+
155
+ See the [Attributes - Coercions](attributes/coercions.md#declarations) docs for task level configurations.
156
+
157
+ ```ruby
158
+ CMDx.configure do |config|
159
+ # Via callable (must respond to `call(value, options)`)
160
+ config.coercions.register :currency, CurrencyCoercion
161
+
162
+ # Via method (must match signature `def coordinates_coercion(value, options)`)
163
+ config.coercions.register :coordinates, :coordinates_coercion
164
+
165
+ # Via proc or lambda
166
+ config.coercions.register :tag_list, proc { |value, options|
167
+ delimiter = options[:delimiter] || ','
168
+ max_tags = options[:max_tags] || 50
169
+
170
+ tags = value.to_s.split(delimiter).map(&:strip).reject(&:empty?)
171
+ tags.first(max_tags)
172
+ }
173
+
174
+ # Remove coercion
175
+ config.coercions.deregister :currency
176
+ end
177
+ ```
178
+
179
+ ### Validators
180
+
181
+ See the [Attributes - Validations](attributes/validations.md#declarations) docs for task level configurations.
182
+
183
+ ```ruby
184
+ CMDx.configure do |config|
185
+ # Via callable (must respond to `call(value, options)`)
186
+ config.validators.register :username, UsernameValidator
187
+
188
+ # Via method (must match signature `def url_validator(value, options)`)
189
+ config.validators.register :url, :url_validator
190
+
191
+ # Via proc or lambda
192
+ config.validators.register :access_token, proc { |value, options|
193
+ expected_prefix = options[:prefix] || "tok_"
194
+ minimum_length = options[:min_length] || 40
195
+
196
+ value.start_with?(expected_prefix) && value.length >= minimum_length
197
+ }
198
+
199
+ # Remove validator
200
+ config.validators.deregister :username
201
+ end
202
+ ```
203
+
204
+ ## Task Configuration
205
+
206
+ ### Settings
207
+
208
+ Override global configuration for specific tasks using `settings`:
209
+
210
+ ```ruby
211
+ class GenerateInvoice < CMDx::Task
212
+ settings(
213
+ # Global configuration overrides
214
+ task_breakpoints: ["failed"], # Breakpoint override
215
+ workflow_breakpoints: [], # Breakpoint override
216
+ backtrace: true, # Toggle backtrace
217
+ backtrace_cleaner: ->(bt) { bt[0..5] }, # Backtrace cleaner
218
+ logger: CustomLogger.new($stdout), # Custom logger
219
+
220
+ # Task configuration settings
221
+ breakpoints: ["failed"], # Contextual pointer for :task_breakpoints and :workflow_breakpoints
222
+ log_level: :info, # Log level override
223
+ log_formatter: CMDx::LogFormatters::Json.new # Log formatter override
224
+ tags: ["billing", "financial"], # Logging tags
225
+ deprecated: true, # Task deprecations
226
+ retries: 3, # Non-fault exception retries
227
+ retry_on: [External::ApiError], # List of exceptions to retry on
228
+ retry_jitter: 1, # Space between retry iteration, eg: current retry num + 1
229
+ rollback_on: ["failed", "skipped"], # Rollback on override
230
+ )
231
+
232
+ def work
233
+ # Your logic here...
234
+ end
235
+ end
236
+ ```
237
+
238
+ !!! warning "Important"
239
+
240
+ Retries reuse the same context. By default, all `StandardError` exceptions (including faults) are retried unless you specify `retry_on` option for specific matches.
241
+
242
+ ### Registrations
243
+
244
+ Register or deregister middlewares, callbacks, coercions, and validators for specific tasks:
245
+
246
+ ```ruby
247
+ class SendCampaignEmail < CMDx::Task
248
+ # Middlewares
249
+ register :middleware, CMDx::Middlewares::Timeout
250
+ deregister :middleware, AuditTrailMiddleware
251
+
252
+ # Callbacks
253
+ register :callback, :on_complete, proc { |task|
254
+ runtime = task.metadata[:runtime]
255
+ Analytics.track("email_campaign.sent", runtime, tags: ["task:#{task.class.name}"])
256
+ }
257
+ deregister :callback, :before_execution, :initialize_user_session
258
+
259
+ # Coercions
260
+ register :coercion, :currency, CurrencyCoercion
261
+ deregister :coercion, :coordinates
262
+
263
+ # Validators
264
+ register :validator, :username, :username_validator
265
+ deregister :validator, :url
266
+
267
+ def work
268
+ # Your logic here...
269
+ end
270
+ end
271
+ ```
272
+
273
+ ## Configuration Management
274
+
275
+ ### Access
276
+
277
+ ```ruby
278
+ # Global configuration access
279
+ CMDx.configuration.logger #=> <Logger instance>
280
+ CMDx.configuration.task_breakpoints #=> ["failed"]
281
+ CMDx.configuration.middlewares.registry #=> [<Middleware>, ...]
282
+
283
+ # Task configuration access
284
+ class ProcessUpload < CMDx::Task
285
+ settings(tags: ["files", "storage"])
286
+
287
+ def work
288
+ self.class.settings[:logger] #=> Global configuration value
289
+ self.class.settings[:tags] #=> Task configuration value => ["files", "storage"]
290
+ end
291
+ end
292
+ ```
293
+
294
+ ### Resetting
295
+
296
+ !!! warning
297
+
298
+ Resetting affects your entire application. Use this primarily in test environments.
299
+
300
+ ```ruby
301
+ # Reset to framework defaults
302
+ CMDx.reset_configuration!
303
+
304
+ # Verify reset
305
+ CMDx.configuration.task_breakpoints #=> ["failed"] (default)
306
+ CMDx.configuration.middlewares.registry #=> Empty registry
307
+
308
+ # Commonly used in test setup (RSpec example)
309
+ RSpec.configure do |config|
310
+ config.before(:each) do
311
+ CMDx.reset_configuration!
312
+ end
313
+ end
314
+ ```