cmdx 1.1.0 → 1.1.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 (87) hide show
  1. checksums.yaml +4 -4
  2. data/.cursor/prompts/docs.md +9 -0
  3. data/.cursor/prompts/rspec.md +13 -12
  4. data/.cursor/prompts/yardoc.md +11 -6
  5. data/CHANGELOG.md +13 -2
  6. data/README.md +1 -0
  7. data/docs/ai_prompts.md +269 -195
  8. data/docs/basics/call.md +124 -58
  9. data/docs/basics/chain.md +190 -160
  10. data/docs/basics/context.md +242 -154
  11. data/docs/basics/setup.md +302 -32
  12. data/docs/callbacks.md +390 -94
  13. data/docs/configuration.md +181 -65
  14. data/docs/deprecation.md +245 -0
  15. data/docs/getting_started.md +161 -39
  16. data/docs/internationalization.md +590 -70
  17. data/docs/interruptions/exceptions.md +135 -118
  18. data/docs/interruptions/faults.md +150 -125
  19. data/docs/interruptions/halt.md +134 -80
  20. data/docs/logging.md +181 -118
  21. data/docs/middlewares.md +150 -377
  22. data/docs/outcomes/result.md +140 -112
  23. data/docs/outcomes/states.md +134 -99
  24. data/docs/outcomes/statuses.md +204 -146
  25. data/docs/parameters/coercions.md +232 -281
  26. data/docs/parameters/defaults.md +224 -169
  27. data/docs/parameters/definitions.md +289 -141
  28. data/docs/parameters/namespacing.md +250 -161
  29. data/docs/parameters/validations.md +260 -133
  30. data/docs/testing.md +191 -197
  31. data/docs/workflows.md +143 -98
  32. data/lib/cmdx/callback.rb +23 -19
  33. data/lib/cmdx/callback_registry.rb +1 -3
  34. data/lib/cmdx/chain_inspector.rb +23 -23
  35. data/lib/cmdx/chain_serializer.rb +38 -19
  36. data/lib/cmdx/coercion.rb +20 -12
  37. data/lib/cmdx/coercion_registry.rb +51 -32
  38. data/lib/cmdx/configuration.rb +84 -31
  39. data/lib/cmdx/context.rb +32 -21
  40. data/lib/cmdx/core_ext/hash.rb +13 -13
  41. data/lib/cmdx/core_ext/module.rb +1 -1
  42. data/lib/cmdx/core_ext/object.rb +12 -12
  43. data/lib/cmdx/correlator.rb +60 -39
  44. data/lib/cmdx/errors.rb +105 -131
  45. data/lib/cmdx/fault.rb +66 -45
  46. data/lib/cmdx/immutator.rb +20 -21
  47. data/lib/cmdx/lazy_struct.rb +78 -70
  48. data/lib/cmdx/log_formatters/json.rb +1 -1
  49. data/lib/cmdx/log_formatters/key_value.rb +1 -1
  50. data/lib/cmdx/log_formatters/line.rb +1 -1
  51. data/lib/cmdx/log_formatters/logstash.rb +1 -1
  52. data/lib/cmdx/log_formatters/pretty_json.rb +1 -1
  53. data/lib/cmdx/log_formatters/pretty_key_value.rb +1 -1
  54. data/lib/cmdx/log_formatters/pretty_line.rb +1 -1
  55. data/lib/cmdx/log_formatters/raw.rb +2 -2
  56. data/lib/cmdx/logger.rb +19 -14
  57. data/lib/cmdx/logger_ansi.rb +33 -17
  58. data/lib/cmdx/logger_serializer.rb +85 -24
  59. data/lib/cmdx/middleware.rb +39 -21
  60. data/lib/cmdx/middleware_registry.rb +4 -3
  61. data/lib/cmdx/parameter.rb +151 -89
  62. data/lib/cmdx/parameter_inspector.rb +34 -21
  63. data/lib/cmdx/parameter_registry.rb +36 -30
  64. data/lib/cmdx/parameter_serializer.rb +21 -14
  65. data/lib/cmdx/result.rb +136 -135
  66. data/lib/cmdx/result_ansi.rb +31 -17
  67. data/lib/cmdx/result_inspector.rb +32 -27
  68. data/lib/cmdx/result_logger.rb +23 -14
  69. data/lib/cmdx/result_serializer.rb +65 -27
  70. data/lib/cmdx/task.rb +234 -113
  71. data/lib/cmdx/task_deprecator.rb +22 -25
  72. data/lib/cmdx/task_processor.rb +89 -88
  73. data/lib/cmdx/task_serializer.rb +27 -14
  74. data/lib/cmdx/utils/monotonic_runtime.rb +2 -4
  75. data/lib/cmdx/validator.rb +25 -16
  76. data/lib/cmdx/validator_registry.rb +53 -31
  77. data/lib/cmdx/validators/exclusion.rb +1 -1
  78. data/lib/cmdx/validators/format.rb +2 -2
  79. data/lib/cmdx/validators/inclusion.rb +2 -2
  80. data/lib/cmdx/validators/length.rb +2 -2
  81. data/lib/cmdx/validators/numeric.rb +3 -3
  82. data/lib/cmdx/validators/presence.rb +2 -2
  83. data/lib/cmdx/version.rb +1 -1
  84. data/lib/cmdx/workflow.rb +54 -33
  85. data/lib/generators/cmdx/task_generator.rb +6 -6
  86. data/lib/generators/cmdx/workflow_generator.rb +6 -6
  87. metadata +3 -1
data/lib/cmdx/task.rb CHANGED
@@ -1,12 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CMDx
4
- # Core task execution system for CMDx framework.
4
+ # Core task implementation providing executable units of work with parameter management.
5
5
  #
6
- # Task provides the foundational functionality for executing business logic
7
- # with parameter validation, middleware support, callback execution, and
8
- # result tracking. Tasks encapsulate reusable business operations with
9
- # comprehensive error handling, logging, and execution state management.
6
+ # Task is the fundamental building block of the CMDx framework, providing a structured
7
+ # approach to implementing business logic with built-in parameter validation, middleware
8
+ # support, callback handling, and comprehensive result tracking. Tasks encapsulate
9
+ # discrete units of work that can be chained together into workflows or executed
10
+ # independently with rich execution context and error handling.
10
11
  class Task
11
12
 
12
13
  cmdx_attr_setting :cmd_settings,
@@ -45,20 +46,28 @@ module CMDx
45
46
  # @return [Result] alias for result
46
47
  alias res result
47
48
 
48
- # Creates a new task instance with the provided execution context.
49
+ # Creates a new task instance with the given execution context.
49
50
  #
50
- # @param context [Hash, Context] execution context data or Context instance
51
+ # Initializes all internal state including context, errors, unique identifier,
52
+ # result tracking, and execution chain. The context parameter supports various
53
+ # input formats and will be normalized into a Context instance.
51
54
  #
52
- # @return [Task] a new task instance ready for execution
55
+ # @param context [Hash, Context, Object] initial execution context and parameters
53
56
  #
54
- # @example Create a task with hash context
57
+ # @return [Task] the newly created task instance
58
+ #
59
+ # @example Create task with hash context
55
60
  # task = MyTask.new(user_id: 123, action: "process")
56
61
  # task.context.user_id #=> 123
57
62
  #
58
- # @example Create a task with existing context
59
- # existing_context = CMDx::Context.build(name: "John")
63
+ # @example Create task with existing context
64
+ # existing_context = OtherTask.call(status: "active")
60
65
  # task = MyTask.new(existing_context)
61
- # task.context.name #=> "John"
66
+ # task.context.status #=> "active"
67
+ #
68
+ # @example Create task with empty context
69
+ # task = MyTask.new
70
+ # task.context #=> empty Context instance
62
71
  def initialize(context = {})
63
72
  context = context.context if context.respond_to?(:context)
64
73
 
@@ -73,95 +82,138 @@ module CMDx
73
82
 
74
83
  class << self
75
84
 
76
- # Registers callbacks for task execution lifecycle events.
77
- #
78
- # These methods are dynamically defined for each callback type and provide
79
- # a clean DSL for registering callbacks that will be executed at specific
80
- # points during task execution.
81
- #
82
- # @param callables [Array<Object>] callback objects to register (symbols, procs, classes)
83
- # @param options [Hash] conditional execution options
84
- # @param block [Proc] optional block to register as a callback
85
- #
86
- # @return [void]
87
- #
88
- # @example Register before_execution callback with symbol
89
- # MyTask.before_execution :setup_database
90
- #
91
- # @example Register before_execution callback with proc
92
- # MyTask.before_execution -> { puts "Starting task execution" }
93
- #
94
- # @example Register before_execution callback with class
95
- # MyTask.before_execution SetupCallback
96
- #
97
- # @example Register before_execution callback with block
98
- # MyTask.before_execution { |task| task.context.started_at = Time.now }
99
- #
100
- # @example Register on_success callback with conditional options
101
- # MyTask.on_success :send_notification, if: -> { Rails.env.production? }
102
- #
103
- # @example Register on_success callback with multiple callables
104
- # MyTask.on_success :log_success, :send_email, :update_metrics
105
85
  CallbackRegistry::TYPES.each do |callback|
86
+ # Registers a callback for the specified lifecycle event.
87
+ #
88
+ # This method is dynamically defined for each callback type supported by
89
+ # CallbackRegistry, allowing tasks to register callbacks for various
90
+ # execution lifecycle events.
91
+ #
92
+ # @param callables [Array<Object>] callback objects or procs to register
93
+ # @param options [Hash] options for callback registration
94
+ # @param block [Proc] optional block to use as callback
95
+ #
96
+ # @return [void]
97
+ #
98
+ # @example Register before_execution callback with symbol
99
+ # class MyTask < CMDx::Task
100
+ # before_execution :setup_database
101
+ # end
102
+ #
103
+ # @example Register before_execution callback with proc
104
+ # class MyTask < CMDx::Task
105
+ # before_execution -> { puts "Starting task execution" }
106
+ # end
107
+ #
108
+ # @example Register before_execution callback with class
109
+ # class MyTask < CMDx::Task
110
+ # before_execution SetupCallback
111
+ # end
112
+ #
113
+ # @example Register before_execution callback with block
114
+ # class MyTask < CMDx::Task
115
+ # before_execution { |task| task.context.started_at = Time.now }
116
+ # end
117
+ #
118
+ # @example Register on_success callback with conditional options
119
+ # class MyTask < CMDx::Task
120
+ # on_success :send_notification, if: -> { Rails.env.production? }
121
+ # end
122
+ #
123
+ # @example Register on_success callback with multiple callables
124
+ # class MyTask < CMDx::Task
125
+ # on_success :log_success, :send_email, :update_metrics
126
+ # end
106
127
  define_method(callback) do |*callables, **options, &block|
107
128
  cmd_callbacks.register(callback, *callables, **options, &block)
108
129
  end
109
130
  end
110
131
 
111
- # Retrieves the value of a task setting.
132
+ # Retrieves a configuration setting value by key.
133
+ #
134
+ # Provides access to task-specific configuration settings that control
135
+ # various aspects of task execution including logging, halt conditions,
136
+ # and custom settings.
112
137
  #
113
- # @param key [Symbol] the setting key to retrieve
138
+ # @param key [Symbol, String] the configuration setting key to retrieve
114
139
  #
115
- # @return [Object] the setting value, processed through cmdx_yield
140
+ # @return [Object] the configuration value, or nil if key doesn't exist
116
141
  #
117
142
  # @example Get logger setting
118
- # MyTask.cmd_setting(:logger) #=> #<Logger:...>
143
+ # MyTask.cmd_setting(:logger) #=> Logger instance
119
144
  #
120
- # @example Get halt setting
121
- # MyTask.cmd_setting(:task_halt) #=> "failed"
145
+ # @example Get custom setting
146
+ # MyTask.cmd_settings!(timeout: 30)
147
+ # MyTask.cmd_setting(:timeout) #=> 30
122
148
  def cmd_setting(key)
123
149
  cmdx_yield(cmd_settings[key])
124
150
  end
125
151
 
126
- # Checks if a task setting key exists.
152
+ # Checks if a configuration setting exists.
127
153
  #
128
- # @param key [Symbol] the setting key to check
154
+ # @param key [Symbol, String] the configuration setting key to check
129
155
  #
130
- # @return [Boolean] true if the setting exists, false otherwise
156
+ # @return [Boolean] true if the setting key exists, false otherwise
131
157
  #
132
- # @example Check if setting exists
158
+ # @example Check for existing setting
133
159
  # MyTask.cmd_setting?(:logger) #=> true
134
- # MyTask.cmd_setting?(:invalid) #=> false
160
+ #
161
+ # @example Check for non-existing setting
162
+ # MyTask.cmd_setting?(:nonexistent) #=> false
135
163
  def cmd_setting?(key)
136
164
  cmd_settings.key?(key)
137
165
  end
138
166
 
139
- # Updates task settings with new values.
167
+ # Updates task configuration settings with the provided options.
140
168
  #
141
- # @param options [Hash] hash of setting keys and values to merge
169
+ # Merges the given options into the existing configuration settings,
170
+ # allowing tasks to customize their execution behavior.
142
171
  #
143
- # @return [Hash] the updated task settings hash
172
+ # @param options [Hash] configuration options to merge
144
173
  #
145
- # @example Update task settings
174
+ # @return [Hash] the updated settings hash
175
+ #
176
+ # @example Set custom timeout
177
+ # MyTask.cmd_settings!(timeout: 60, retries: 3)
178
+ #
179
+ # @example Override halt condition
146
180
  # MyTask.cmd_settings!(task_halt: ["failed", "error"])
147
- # MyTask.cmd_setting(:task_halt) #=> ["failed", "error"]
148
181
  def cmd_settings!(**options)
149
182
  cmd_settings.merge!(options)
150
183
  end
151
184
 
152
185
  # Registers middleware, callbacks, validators, or coercions with the task.
153
186
  #
154
- # @param type [Symbol] the type of registration (:middleware, :callback, :validator, :coercion)
155
- # @param object [Object] the object to register
156
- # @param args [Array] additional arguments passed to the registration method
187
+ # Provides a unified interface for registering various types of task
188
+ # extensions that modify or enhance task execution behavior.
189
+ #
190
+ # @param type [Symbol] the type of extension to register (:middleware, :callback, :validator, :coercion)
191
+ # @param object [Object] the extension object to register
192
+ # @param args [Array] additional arguments for registration
157
193
  #
158
194
  # @return [void]
159
195
  #
196
+ # @raise [ArgumentError] if an unsupported type is provided
197
+ #
198
+ # @example Register coercion
199
+ # class MyTask < CMDx::Task
200
+ # use :coercion, TemperatureCoercion
201
+ # end
202
+ #
203
+ # @example Register validator
204
+ # class MyTask < CMDx::Task
205
+ # use :validator, ZipcodeValidator, country: "US"
206
+ # end
207
+ #
160
208
  # @example Register middleware
161
- # MyTask.use(:middleware, TimeoutMiddleware, timeout: 30)
209
+ # class MyTask < CMDx::Task
210
+ # use :middleware, CMDx::Middlewares::Timeout.new(seconds: 30)
211
+ # end
162
212
  #
163
213
  # @example Register callback
164
- # MyTask.use(:callback, :before_execution, MyCallback)
214
+ # class MyTask < CMDx::Task
215
+ # use :callback, :before, LogCallback.new
216
+ # end
165
217
  def use(type, object, ...)
166
218
  case type
167
219
  when :middleware
@@ -175,77 +227,120 @@ module CMDx
175
227
  end
176
228
  end
177
229
 
178
- # Defines optional parameters for the task.
230
+ # Defines optional parameters for the task with validation and coercion.
231
+ #
232
+ # Creates parameter definitions that are not required for task execution
233
+ # but will be validated and coerced if provided. Supports nested parameter
234
+ # structures through block syntax.
179
235
  #
180
236
  # @param attributes [Array<Symbol>] parameter names to define as optional
181
237
  # @param options [Hash] parameter configuration options
238
+ # @option options [Symbol, Array<Symbol>] :type parameter type(s) for coercion
239
+ # @option options [Object] :default default value if parameter not provided
240
+ # @option options [Hash] :validates validation rules to apply
182
241
  # @param block [Proc] optional block for defining nested parameters
183
242
  #
184
- # @return [void]
243
+ # @return [Array<Parameter>] the created parameter definitions
185
244
  #
186
- # @example Define optional parameters
187
- # MyTask.optional :name, :email, type: :string
245
+ # @example Define simple optional parameters
246
+ # class MyTask < CMDx::Task
247
+ # optional :name, :email, type: :string
248
+ # optional :age, type: :integer, default: 0
249
+ # end
188
250
  #
189
251
  # @example Define optional parameter with validation
190
- # MyTask.optional :age, type: :integer, validate: { numeric: { greater_than: 0 } }
252
+ # class MyTask < CMDx::Task
253
+ # optional :score, type: :integer, validates: { numeric: { greater_than: 0 } }
254
+ # end
255
+ #
256
+ # @example Define nested optional parameters
257
+ # class MyTask < CMDx::Task
258
+ # optional :user, type: :hash do
259
+ # required :name, type: :string
260
+ # optional :age, type: :integer
261
+ # end
262
+ # end
191
263
  def optional(*attributes, **options, &)
192
264
  parameters = Parameter.optional(*attributes, **options.merge(klass: self), &)
193
265
  cmd_parameters.registry.concat(parameters)
194
266
  end
195
267
 
196
- # Defines required parameters for the task.
268
+ # Defines required parameters for the task with validation and coercion.
269
+ #
270
+ # Creates parameter definitions that must be provided for successful task
271
+ # execution. Missing required parameters will cause task validation to fail.
272
+ # Supports nested parameter structures through block syntax.
197
273
  #
198
274
  # @param attributes [Array<Symbol>] parameter names to define as required
199
275
  # @param options [Hash] parameter configuration options
276
+ # @option options [Symbol, Array<Symbol>] :type parameter type(s) for coercion
277
+ # @option options [Object] :default default value if parameter not provided
278
+ # @option options [Hash] :validates validation rules to apply
200
279
  # @param block [Proc] optional block for defining nested parameters
201
280
  #
202
- # @return [void]
281
+ # @return [Array<Parameter>] the created parameter definitions
282
+ #
283
+ # @example Define simple required parameters
284
+ # class MyTask < CMDx::Task
285
+ # required :user_id, type: :integer
286
+ # required :action, type: :string
287
+ # end
203
288
  #
204
- # @example Define required parameters
205
- # MyTask.required :user_id, :action, type: :string
289
+ # @example Define required parameter with validation
290
+ # class MyTask < CMDx::Task
291
+ # required :email, type: :string, validates: { format: /@/ }
292
+ # end
206
293
  #
207
- # @example Define required parameter with nested structure
208
- # MyTask.required :user, type: :hash do
209
- # required :name, type: :string
210
- # optional :email, type: :string
294
+ # @example Define nested required parameters
295
+ # class MyTask < CMDx::Task
296
+ # required :payment, type: :hash do
297
+ # required :amount, type: :big_decimal
298
+ # required :currency, type: :string
299
+ # optional :description, type: :string
300
+ # end
211
301
  # end
212
302
  def required(*attributes, **options, &)
213
303
  parameters = Parameter.required(*attributes, **options.merge(klass: self), &)
214
304
  cmd_parameters.registry.concat(parameters)
215
305
  end
216
306
 
217
- # Executes the task with fault tolerance and returns the result.
307
+ # Executes a task instance and returns the result without raising exceptions.
308
+ #
309
+ # Creates a new task instance with the provided context, processes it through
310
+ # the complete execution pipeline, and returns the result. This method will
311
+ # not raise exceptions for task failures but will capture them in the result.
218
312
  #
219
- # @param args [Array] arguments passed to the task constructor
313
+ # @param args [Array] arguments passed to task constructor
220
314
  #
221
- # @return [Result] the task execution result
315
+ # @return [Result] the execution result containing state, status, and metadata
222
316
  #
223
- # @example Execute task with fault tolerance
224
- # result = MyTask.call(user_id: 123)
225
- # result.success? #=> true
226
- # result.context.user_id #=> 123
317
+ # @example Execute task
318
+ # result = MyTask.call(user_id: 123, action: "process")
319
+ # puts result.status #=> "success" or "failed" or "skipped"
227
320
  def call(...)
228
321
  instance = new(...)
229
322
  instance.process
230
323
  instance.result
231
324
  end
232
325
 
233
- # Executes the task with strict fault handling and returns the result.
326
+ # Executes a task instance and returns the result, raising exceptions on failure.
234
327
  #
235
- # @param args [Array] arguments passed to the task constructor
328
+ # Creates a new task instance with the provided context, processes it through
329
+ # the complete execution pipeline, and returns the result. This method will
330
+ # raise appropriate fault exceptions if the task fails or is skipped.
236
331
  #
237
- # @return [Result] the task execution result
332
+ # @param args [Array] arguments passed to task constructor
238
333
  #
239
- # @raise [Fault] if the task fails and task_halt setting includes the failure status
334
+ # @return [Result] the execution result containing state, status, and metadata
240
335
  #
241
- # @example Execute task with strict fault handling
242
- # result = MyTask.call!(user_id: 123)
243
- # result.success? #=> true
336
+ # @raise [Failed] when task execution fails
337
+ # @raise [Skipped] when task execution is skipped
244
338
  #
245
- # @example Handling fault on failure
339
+ # @example Execute task
246
340
  # begin
247
- # MyTask.call!(invalid_data: true)
248
- # rescue CMDx::Fault => e
341
+ # result = MyTask.call!(user_id: 123)
342
+ # puts "Success: #{result.status}"
343
+ # rescue CMDx::Failed => e
249
344
  # puts "Task failed: #{e.message}"
250
345
  # end
251
346
  def call!(...)
@@ -258,58 +353,84 @@ module CMDx
258
353
 
259
354
  # Abstract method that must be implemented by task subclasses.
260
355
  #
261
- # This method contains the core business logic to be executed by the task.
262
- # Subclasses must override this method to provide their specific implementation.
356
+ # This method contains the actual business logic for the task. Subclasses
357
+ # must override this method to provide their specific implementation.
358
+ # The method has access to the task's context, can modify it, and can
359
+ # use skip!, fail!, or throw! to control execution flow.
263
360
  #
264
361
  # @return [void]
265
362
  #
266
- # @raise [UndefinedCallError] if not implemented by subclass
363
+ # @raise [UndefinedCallError] always raised in the base Task class
267
364
  #
268
365
  # @example Implement in a subclass
269
366
  # class ProcessUserTask < CMDx::Task
367
+ # required :user_id, type: :integer
368
+ #
270
369
  # def call
271
- # # Business logic here
272
- # context.processed = true
370
+ # user = User.find(context.user_id)
371
+ # skip!(reason: "User already processed") if user.processed?
372
+ #
373
+ # user.process!
374
+ # context.processed_at = Time.now
273
375
  # end
274
376
  # end
275
377
  def call
276
378
  raise UndefinedCallError, "call method not defined in #{self.class.name}"
277
379
  end
278
380
 
279
- # Performs task execution with middleware support and fault tolerance.
381
+ # Executes the task through the middleware pipeline without raising exceptions.
382
+ #
383
+ # Processes the task by running it through all registered middleware and
384
+ # the TaskProcessor. This method captures exceptions and converts them
385
+ # into result states rather than propagating them.
280
386
  #
281
387
  # @return [void]
282
388
  #
283
- # @example Task execution with middleware
284
- # task = MyTask.new(user_id: 123)
389
+ # @example Process a task instance
390
+ # task = MyTask.new(data: "input")
285
391
  # task.process
286
- # task.result.success? #=> true
392
+ # puts task.result.status #=> "success", "failed", or "skipped"
287
393
  def process
288
394
  cmd_middlewares.call(self) { |task| TaskProcessor.call(task) }
289
395
  end
290
396
 
291
- # Performs task execution with middleware support and strict fault handling.
397
+ # Executes the task through the middleware pipeline, raising exceptions on failure.
398
+ #
399
+ # Processes the task by running it through all registered middleware and
400
+ # the TaskProcessor. This method will raise appropriate fault exceptions
401
+ # if the task fails or is skipped.
292
402
  #
293
403
  # @return [void]
294
404
  #
295
- # @raise [Fault] if task fails and task_halt setting includes the failure status
405
+ # @raise [Failed] when task execution fails
406
+ # @raise [Skipped] when task execution is skipped
296
407
  #
297
- # @example Task execution with strict fault handling
298
- # task = MyTask.new(user_id: 123)
299
- # task.process!
300
- # task.result.success? #=> true
408
+ # @example Process a task instance with exception handling
409
+ # task = RiskyTask.new(data: "input")
410
+ # begin
411
+ # task.process!
412
+ # puts "Task completed successfully"
413
+ # rescue CMDx::Failed => e
414
+ # puts "Task failed: #{e.message}"
415
+ # end
301
416
  def process!
302
417
  cmd_middlewares.call(self) { |task| TaskProcessor.call!(task) }
303
418
  end
304
419
 
305
- # Creates a logger instance for this task.
420
+ # Creates a logger instance configured for this task.
306
421
  #
307
- # @return [Logger] logger instance configured for this task
422
+ # Returns a logger instance that is pre-configured with the task's
423
+ # settings and context information for consistent logging throughout
424
+ # task execution.
308
425
  #
309
- # @example Getting task logger
310
- # task = MyTask.new
311
- # logger = task.send(:logger)
312
- # logger.info("Task started")
426
+ # @return [Logger] configured logger instance for this task
427
+ #
428
+ # @example Log task execution
429
+ # def call
430
+ # logger.info "Starting user processing"
431
+ # # ... task logic ...
432
+ # logger.info "User processing completed"
433
+ # end
313
434
  def logger
314
435
  Logger.call(self)
315
436
  end
@@ -1,52 +1,49 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CMDx
4
- # Handles deprecation checking for CMDx tasks.
4
+ # Task deprecation system for CMDx tasks.
5
5
  #
6
- # This module provides functionality to check if a task is marked as deprecated
7
- # and raise appropriate errors when deprecated tasks are instantiated. It integrates
8
- # with the task lifecycle to prevent usage of deprecated functionality.
6
+ # This module provides a centralized system for handling task deprecation
7
+ # warnings and errors. It supports multiple deprecation modes including
8
+ # raising exceptions, logging warnings, or issuing Ruby warnings based
9
+ # on task configuration settings.
9
10
  module TaskDeprecator
10
11
 
11
12
  module_function
12
13
 
13
- # Checks deprecation status of a task and handles it according to the configured behavior.
14
- #
15
- # This method examines the task's deprecation setting and takes appropriate action:
16
- # - :raise - raises DeprecationError to prevent task execution
17
- # - :warn - issues Ruby deprecation warning
18
- # - :log or true - logs deprecation warning
19
- # - nil or false - allows task execution without warnings
20
- #
21
- # @param task [Task] the task instance to check for deprecation
14
+ # Processes task deprecation based on the task's deprecated setting.
22
15
  #
16
+ # @param task [CMDx::Task] the task instance to check for deprecation
23
17
  # @return [void]
18
+ # @raise [DeprecationError] when task's deprecated setting is :error
24
19
  #
25
- # @raise [DeprecationError] when task is marked with deprecated: :raise
26
- #
27
- # @example Task with raise deprecation setting
20
+ # @example Handle task with raise deprecation
28
21
  # class MyTask < CMDx::Task
29
- # cmd_settings! deprecated: :raise
22
+ # cmd_setting!(deprecated: :error)
30
23
  # end
31
- # CMDx::TaskDeprecator.call(MyTask.new) # raises DeprecationError
24
+ # task = MyTask.new
25
+ # TaskDeprecator.call(task) # raises DeprecationError
32
26
  #
33
- # @example Task with a proc deprecation setting
27
+ # @example Handle task with log deprecation
34
28
  # class MyTask < CMDx::Task
35
- # cmd_settings! deprecated: -> { Time.now.year > 2025 ? :raise : :log }
29
+ # cmd_setting!(deprecated: :log)
36
30
  # end
37
- # CMDx::TaskDeprecator.call(MyTask.new) # issues warnings
31
+ # task = MyTask.new
32
+ # TaskDeprecator.call(task) # logs warning via task.logger
38
33
  #
39
- # @example Task with no deprecation setting
34
+ # @example Handle task with warn deprecation
40
35
  # class MyTask < CMDx::Task
36
+ # cmd_setting!(deprecated: :warning)
41
37
  # end
42
- # CMDx::TaskDeprecator.call(MyTask.new) # no action taken
38
+ # task = MyTask.new
39
+ # TaskDeprecator.call(task) # issues Ruby warning
43
40
  def call(task)
44
41
  case task.cmd_setting(:deprecated)
45
- when :raise
42
+ when :error
46
43
  raise(DeprecationError, "#{task.class.name} usage prohibited")
47
44
  when :log, true
48
45
  task.logger.warn { "DEPRECATED: migrate to replacement or discontinue use" }
49
- when :warn
46
+ when :warning
50
47
  warn("[#{task.class.name}] DEPRECATED: migrate to replacement or discontinue use", category: :deprecated)
51
48
  end
52
49
  end