cmdx 0.5.0 → 1.0.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 (151) hide show
  1. checksums.yaml +4 -4
  2. data/.DS_Store +0 -0
  3. data/.cursor/rules/cursor-instructions.mdc +6 -0
  4. data/.rubocop.yml +19 -1
  5. data/.ruby-version +1 -1
  6. data/CHANGELOG.md +95 -28
  7. data/README.md +73 -25
  8. data/docs/ai_prompts.md +319 -0
  9. data/docs/basics/call.md +234 -14
  10. data/docs/basics/chain.md +280 -0
  11. data/docs/basics/context.md +241 -33
  12. data/docs/basics/setup.md +85 -12
  13. data/docs/callbacks.md +283 -0
  14. data/docs/configuration.md +155 -30
  15. data/docs/getting_started.md +145 -22
  16. data/docs/internationalization.md +148 -0
  17. data/docs/interruptions/exceptions.md +198 -11
  18. data/docs/interruptions/faults.md +196 -44
  19. data/docs/interruptions/halt.md +188 -35
  20. data/docs/logging.md +204 -53
  21. data/docs/middlewares.md +745 -0
  22. data/docs/outcomes/result.md +305 -10
  23. data/docs/outcomes/states.md +212 -31
  24. data/docs/outcomes/statuses.md +284 -30
  25. data/docs/parameters/coercions.md +411 -29
  26. data/docs/parameters/defaults.md +258 -25
  27. data/docs/parameters/definitions.md +247 -72
  28. data/docs/parameters/namespacing.md +259 -27
  29. data/docs/parameters/validations.md +173 -168
  30. data/docs/testing.md +560 -0
  31. data/docs/tips_and_tricks.md +103 -42
  32. data/docs/workflows.md +329 -0
  33. data/lib/cmdx/.DS_Store +0 -0
  34. data/lib/cmdx/callback.rb +69 -0
  35. data/lib/cmdx/callback_registry.rb +106 -0
  36. data/lib/cmdx/chain.rb +190 -0
  37. data/lib/cmdx/chain_inspector.rb +149 -0
  38. data/lib/cmdx/chain_serializer.rb +175 -0
  39. data/lib/cmdx/coercions/array.rb +37 -0
  40. data/lib/cmdx/coercions/big_decimal.rb +33 -0
  41. data/lib/cmdx/coercions/boolean.rb +41 -1
  42. data/lib/cmdx/coercions/complex.rb +31 -0
  43. data/lib/cmdx/coercions/date.rb +39 -0
  44. data/lib/cmdx/coercions/date_time.rb +39 -0
  45. data/lib/cmdx/coercions/float.rb +31 -0
  46. data/lib/cmdx/coercions/hash.rb +42 -0
  47. data/lib/cmdx/coercions/integer.rb +32 -0
  48. data/lib/cmdx/coercions/rational.rb +31 -0
  49. data/lib/cmdx/coercions/string.rb +31 -0
  50. data/lib/cmdx/coercions/time.rb +39 -0
  51. data/lib/cmdx/coercions/virtual.rb +31 -0
  52. data/lib/cmdx/configuration.rb +217 -9
  53. data/lib/cmdx/context.rb +173 -2
  54. data/lib/cmdx/core_ext/hash.rb +72 -0
  55. data/lib/cmdx/core_ext/module.rb +94 -0
  56. data/lib/cmdx/core_ext/object.rb +105 -0
  57. data/lib/cmdx/correlator.rb +217 -0
  58. data/lib/cmdx/error.rb +210 -8
  59. data/lib/cmdx/errors.rb +256 -1
  60. data/lib/cmdx/fault.rb +177 -2
  61. data/lib/cmdx/faults.rb +158 -2
  62. data/lib/cmdx/immutator.rb +121 -2
  63. data/lib/cmdx/lazy_struct.rb +261 -18
  64. data/lib/cmdx/log_formatters/json.rb +46 -0
  65. data/lib/cmdx/log_formatters/key_value.rb +46 -0
  66. data/lib/cmdx/log_formatters/line.rb +54 -0
  67. data/lib/cmdx/log_formatters/logstash.rb +64 -0
  68. data/lib/cmdx/log_formatters/pretty_json.rb +57 -0
  69. data/lib/cmdx/log_formatters/pretty_key_value.rb +51 -0
  70. data/lib/cmdx/log_formatters/pretty_line.rb +60 -0
  71. data/lib/cmdx/log_formatters/raw.rb +54 -0
  72. data/lib/cmdx/logger.rb +85 -0
  73. data/lib/cmdx/logger_ansi.rb +93 -7
  74. data/lib/cmdx/logger_serializer.rb +116 -0
  75. data/lib/cmdx/middleware.rb +74 -0
  76. data/lib/cmdx/middleware_registry.rb +106 -0
  77. data/lib/cmdx/middlewares/correlate.rb +266 -0
  78. data/lib/cmdx/middlewares/timeout.rb +232 -0
  79. data/lib/cmdx/parameter.rb +228 -1
  80. data/lib/cmdx/parameter_inspector.rb +61 -0
  81. data/lib/cmdx/parameter_registry.rb +125 -0
  82. data/lib/cmdx/parameter_serializer.rb +83 -0
  83. data/lib/cmdx/parameter_validator.rb +62 -0
  84. data/lib/cmdx/parameter_value.rb +109 -1
  85. data/lib/cmdx/parameters_inspector.rb +59 -0
  86. data/lib/cmdx/parameters_serializer.rb +102 -0
  87. data/lib/cmdx/railtie.rb +123 -3
  88. data/lib/cmdx/result.rb +367 -25
  89. data/lib/cmdx/result_ansi.rb +105 -9
  90. data/lib/cmdx/result_inspector.rb +76 -0
  91. data/lib/cmdx/result_logger.rb +90 -3
  92. data/lib/cmdx/result_serializer.rb +137 -0
  93. data/lib/cmdx/rspec/result_matchers.rb +917 -0
  94. data/lib/cmdx/rspec/task_matchers.rb +570 -0
  95. data/lib/cmdx/task.rb +405 -37
  96. data/lib/cmdx/task_serializer.rb +74 -2
  97. data/lib/cmdx/utils/ansi_color.rb +95 -0
  98. data/lib/cmdx/utils/log_timestamp.rb +48 -0
  99. data/lib/cmdx/utils/monotonic_runtime.rb +71 -4
  100. data/lib/cmdx/utils/name_affix.rb +78 -0
  101. data/lib/cmdx/validators/custom.rb +82 -0
  102. data/lib/cmdx/validators/exclusion.rb +94 -0
  103. data/lib/cmdx/validators/format.rb +102 -8
  104. data/lib/cmdx/validators/inclusion.rb +104 -0
  105. data/lib/cmdx/validators/length.rb +128 -0
  106. data/lib/cmdx/validators/numeric.rb +128 -0
  107. data/lib/cmdx/validators/presence.rb +93 -7
  108. data/lib/cmdx/version.rb +7 -1
  109. data/lib/cmdx/workflow.rb +394 -0
  110. data/lib/cmdx.rb +25 -64
  111. data/lib/generators/cmdx/install_generator.rb +37 -1
  112. data/lib/generators/cmdx/task_generator.rb +69 -1
  113. data/lib/generators/cmdx/templates/install.rb +43 -15
  114. data/lib/generators/cmdx/workflow_generator.rb +109 -0
  115. data/lib/locales/ar.yml +36 -0
  116. data/lib/locales/cs.yml +36 -0
  117. data/lib/locales/da.yml +36 -0
  118. data/lib/locales/de.yml +36 -0
  119. data/lib/locales/el.yml +36 -0
  120. data/lib/locales/en.yml +20 -20
  121. data/lib/locales/es.yml +20 -20
  122. data/lib/locales/fi.yml +36 -0
  123. data/lib/locales/fr.yml +36 -0
  124. data/lib/locales/he.yml +36 -0
  125. data/lib/locales/hi.yml +36 -0
  126. data/lib/locales/it.yml +36 -0
  127. data/lib/locales/ja.yml +36 -0
  128. data/lib/locales/ko.yml +36 -0
  129. data/lib/locales/nl.yml +36 -0
  130. data/lib/locales/no.yml +36 -0
  131. data/lib/locales/pl.yml +36 -0
  132. data/lib/locales/pt.yml +36 -0
  133. data/lib/locales/ru.yml +36 -0
  134. data/lib/locales/sv.yml +36 -0
  135. data/lib/locales/th.yml +36 -0
  136. data/lib/locales/tr.yml +36 -0
  137. data/lib/locales/vi.yml +36 -0
  138. data/lib/locales/zh.yml +36 -0
  139. metadata +77 -15
  140. data/docs/basics/run.md +0 -34
  141. data/docs/batch.md +0 -53
  142. data/docs/example.md +0 -82
  143. data/docs/hooks.md +0 -62
  144. data/lib/cmdx/batch.rb +0 -43
  145. data/lib/cmdx/parameters.rb +0 -35
  146. data/lib/cmdx/run.rb +0 -39
  147. data/lib/cmdx/run_inspector.rb +0 -26
  148. data/lib/cmdx/run_serializer.rb +0 -20
  149. data/lib/cmdx/task_hook.rb +0 -18
  150. data/lib/generators/cmdx/batch_generator.rb +0 -30
  151. /data/lib/generators/cmdx/templates/{batch.rb.tt → workflow.rb.tt} +0 -0
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cmdx
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juan Gomez
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-03-21 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: bigdecimal
@@ -51,6 +51,20 @@ dependencies:
51
51
  - - ">="
52
52
  - !ruby/object:Gem::Version
53
53
  version: '0'
54
+ - !ruby/object:Gem::Dependency
55
+ name: zeitwerk
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
54
68
  - !ruby/object:Gem::Dependency
55
69
  name: bundler
56
70
  requirement: !ruby/object:Gem::Requirement
@@ -65,6 +79,20 @@ dependencies:
65
79
  - - ">="
66
80
  - !ruby/object:Gem::Version
67
81
  version: '0'
82
+ - !ruby/object:Gem::Dependency
83
+ name: ostruct
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
68
96
  - !ruby/object:Gem::Dependency
69
97
  name: rake
70
98
  requirement: !ruby/object:Gem::Requirement
@@ -158,6 +186,7 @@ extensions: []
158
186
  extra_rdoc_files: []
159
187
  files:
160
188
  - ".DS_Store"
189
+ - ".cursor/rules/cursor-instructions.mdc"
161
190
  - ".rspec"
162
191
  - ".rubocop.yml"
163
192
  - ".ruby-version"
@@ -166,19 +195,20 @@ files:
166
195
  - LICENSE.txt
167
196
  - README.md
168
197
  - Rakefile
198
+ - docs/ai_prompts.md
169
199
  - docs/basics/call.md
200
+ - docs/basics/chain.md
170
201
  - docs/basics/context.md
171
- - docs/basics/run.md
172
202
  - docs/basics/setup.md
173
- - docs/batch.md
203
+ - docs/callbacks.md
174
204
  - docs/configuration.md
175
- - docs/example.md
176
205
  - docs/getting_started.md
177
- - docs/hooks.md
206
+ - docs/internationalization.md
178
207
  - docs/interruptions/exceptions.md
179
208
  - docs/interruptions/faults.md
180
209
  - docs/interruptions/halt.md
181
210
  - docs/logging.md
211
+ - docs/middlewares.md
182
212
  - docs/outcomes/result.md
183
213
  - docs/outcomes/states.md
184
214
  - docs/outcomes/statuses.md
@@ -187,10 +217,16 @@ files:
187
217
  - docs/parameters/definitions.md
188
218
  - docs/parameters/namespacing.md
189
219
  - docs/parameters/validations.md
220
+ - docs/testing.md
190
221
  - docs/tips_and_tricks.md
222
+ - docs/workflows.md
191
223
  - lib/cmdx.rb
192
224
  - lib/cmdx/.DS_Store
193
- - lib/cmdx/batch.rb
225
+ - lib/cmdx/callback.rb
226
+ - lib/cmdx/callback_registry.rb
227
+ - lib/cmdx/chain.rb
228
+ - lib/cmdx/chain_inspector.rb
229
+ - lib/cmdx/chain_serializer.rb
194
230
  - lib/cmdx/coercions/array.rb
195
231
  - lib/cmdx/coercions/big_decimal.rb
196
232
  - lib/cmdx/coercions/boolean.rb
@@ -209,6 +245,7 @@ files:
209
245
  - lib/cmdx/core_ext/hash.rb
210
246
  - lib/cmdx/core_ext/module.rb
211
247
  - lib/cmdx/core_ext/object.rb
248
+ - lib/cmdx/correlator.rb
212
249
  - lib/cmdx/error.rb
213
250
  - lib/cmdx/errors.rb
214
251
  - lib/cmdx/fault.rb
@@ -226,12 +263,16 @@ files:
226
263
  - lib/cmdx/logger.rb
227
264
  - lib/cmdx/logger_ansi.rb
228
265
  - lib/cmdx/logger_serializer.rb
266
+ - lib/cmdx/middleware.rb
267
+ - lib/cmdx/middleware_registry.rb
268
+ - lib/cmdx/middlewares/correlate.rb
269
+ - lib/cmdx/middlewares/timeout.rb
229
270
  - lib/cmdx/parameter.rb
230
271
  - lib/cmdx/parameter_inspector.rb
272
+ - lib/cmdx/parameter_registry.rb
231
273
  - lib/cmdx/parameter_serializer.rb
232
274
  - lib/cmdx/parameter_validator.rb
233
275
  - lib/cmdx/parameter_value.rb
234
- - lib/cmdx/parameters.rb
235
276
  - lib/cmdx/parameters_inspector.rb
236
277
  - lib/cmdx/parameters_serializer.rb
237
278
  - lib/cmdx/railtie.rb
@@ -240,11 +281,9 @@ files:
240
281
  - lib/cmdx/result_inspector.rb
241
282
  - lib/cmdx/result_logger.rb
242
283
  - lib/cmdx/result_serializer.rb
243
- - lib/cmdx/run.rb
244
- - lib/cmdx/run_inspector.rb
245
- - lib/cmdx/run_serializer.rb
284
+ - lib/cmdx/rspec/result_matchers.rb
285
+ - lib/cmdx/rspec/task_matchers.rb
246
286
  - lib/cmdx/task.rb
247
- - lib/cmdx/task_hook.rb
248
287
  - lib/cmdx/task_serializer.rb
249
288
  - lib/cmdx/utils/ansi_color.rb
250
289
  - lib/cmdx/utils/log_timestamp.rb
@@ -258,14 +297,37 @@ files:
258
297
  - lib/cmdx/validators/numeric.rb
259
298
  - lib/cmdx/validators/presence.rb
260
299
  - lib/cmdx/version.rb
261
- - lib/generators/cmdx/batch_generator.rb
300
+ - lib/cmdx/workflow.rb
262
301
  - lib/generators/cmdx/install_generator.rb
263
302
  - lib/generators/cmdx/task_generator.rb
264
- - lib/generators/cmdx/templates/batch.rb.tt
265
303
  - lib/generators/cmdx/templates/install.rb
266
304
  - lib/generators/cmdx/templates/task.rb.tt
305
+ - lib/generators/cmdx/templates/workflow.rb.tt
306
+ - lib/generators/cmdx/workflow_generator.rb
307
+ - lib/locales/ar.yml
308
+ - lib/locales/cs.yml
309
+ - lib/locales/da.yml
310
+ - lib/locales/de.yml
311
+ - lib/locales/el.yml
267
312
  - lib/locales/en.yml
268
313
  - lib/locales/es.yml
314
+ - lib/locales/fi.yml
315
+ - lib/locales/fr.yml
316
+ - lib/locales/he.yml
317
+ - lib/locales/hi.yml
318
+ - lib/locales/it.yml
319
+ - lib/locales/ja.yml
320
+ - lib/locales/ko.yml
321
+ - lib/locales/nl.yml
322
+ - lib/locales/no.yml
323
+ - lib/locales/pl.yml
324
+ - lib/locales/pt.yml
325
+ - lib/locales/ru.yml
326
+ - lib/locales/sv.yml
327
+ - lib/locales/th.yml
328
+ - lib/locales/tr.yml
329
+ - lib/locales/vi.yml
330
+ - lib/locales/zh.yml
269
331
  homepage: https://github.com/drexed/cmdx
270
332
  licenses:
271
333
  - MIT
@@ -290,7 +352,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
290
352
  - !ruby/object:Gem::Version
291
353
  version: '0'
292
354
  requirements: []
293
- rubygems_version: 3.6.5
355
+ rubygems_version: 3.6.9
294
356
  specification_version: 4
295
357
  summary: Command (aka service) objects with intent
296
358
  test_files: []
data/docs/basics/run.md DELETED
@@ -1,34 +0,0 @@
1
- # Basics - Run
2
-
3
- A run represents a group of tasks executed as part of collection.
4
-
5
- When building complex tasks, it's best to pass the parents context to subtasks
6
- (unless necessary or preventative) so that it gains automated indexing and the
7
- parents `run_id`. This makes it easy to identify all tasks involved in one
8
- execution from logging and stdout console calls.
9
-
10
- ```ruby
11
- class ProcessOrderTask < CMDx::Task
12
-
13
- def call
14
- # Subtasks inherit the ProcessOrderTask run_id:
15
- SendEmailConfirmationTask.call(context)
16
- NotifyPartnerWarehousesTask.call(context)
17
- end
18
-
19
- end
20
-
21
- result = ProcessOrderTask.call
22
- puts result.run.to_s
23
-
24
- # Task name Index Run ID Task ID etc
25
- # -----------------------------------------------------------------
26
- #=> ProcessOrderTask 0 foobar123 abc123 ...
27
- #=> SendEmailConfirmationTask 1 foobar123 def456 ...
28
- #=> NotifyPartnerWarehousesTask 2 foobar123 ghi789 ...
29
- ```
30
-
31
- ---
32
-
33
- - **Prev:** [Basics - Context](https://github.com/drexed/cmdx/blob/main/docs/basics/context.md)
34
- - **Next:** [Interruptions - Halt](https://github.com/drexed/cmdx/blob/main/docs/interruptions/halt.md)
data/docs/batch.md DELETED
@@ -1,53 +0,0 @@
1
- # Batch
2
-
3
- A CMDx::Batch is a task that calls other tasks in a linear fashion. The
4
- context is passed down to each task, building on it knowledge with
5
- each step. This is useful for composing multiple steps into one call.
6
-
7
- > [!WARNING]
8
- > Do **NOT** define a call method in this class. The batch class automatically
9
- > defines the call logic.
10
-
11
- ```ruby
12
- class BatchProcessCheckout < CMDx::Batch
13
-
14
- # Task level settings:
15
- task_settings!(batch_halt: CMDx::Result::FAILED)
16
-
17
- # Single declaration:
18
- process FinalizeInvoiceTask
19
-
20
- # Multiple declarations:
21
- process SendConfirmationEmailTask, SendConfirmationTextTask
22
-
23
- # With options (applies to all declared in that group):
24
- process BatchNotifyPartnerWarehouses, batch_halt: [CMDx::Result::SKIPPED, CMDx::Result::FAILED]
25
- process BatchNotifyUsaWarehouses, unless: proc { context.invoice.fulfilled_in_house? }
26
-
27
- end
28
- ```
29
-
30
- > [!IMPORTANT]
31
- > Process steps are executed in the order they are declared (FIFO: first in, first out).
32
-
33
- The `process` method support the following options:
34
-
35
- | Option | Description |
36
- | ------------- | ----------- |
37
- | `:if` | Specifies a callable method, proc or string to determine if processing steps should occur. |
38
- | `:unless` | Specifies a callable method, proc, or string to determine if processing steps should not occur. |
39
- | `:batch_halt` | Sets which result statuses processing of further steps should be prevented. (default: `CMDx::Result::FAILED`) |
40
-
41
- > [!NOTE]
42
- > Batches stop execution on `failed` by default. This is due to the concept
43
- > of `skipped` being a bypass mechanism, rather than a choke point in execution.
44
-
45
- ## Generator
46
-
47
- Run `rails g cmdx:batch [NAME]` to create a batch task template file under `app/cmds`.
48
- Tasks will inherit from `ApplicationBatch` if available or fall back to `CMDx::Batch`.
49
-
50
- ---
51
-
52
- - **Prev:** [Hooks](https://github.com/drexed/cmdx/blob/main/docs/hooks.md)
53
- - **Next:** [Logging](https://github.com/drexed/cmdx/blob/main/docs/logging.md)
data/docs/example.md DELETED
@@ -1,82 +0,0 @@
1
- # Example
2
-
3
- The following is a full example of task that is commonly implemented.
4
-
5
- ## Setup
6
-
7
- ```ruby
8
- class ProcessOrderTask < CMDx::Task
9
-
10
- required :order
11
- required :billing_details, :shipping_details, from: :order
12
-
13
- optional :package do
14
- required :delivery_company, default: -> { Current.account.premium? ? "UPS" : "DHL" }
15
- optional :weight, :volume, type: :float
16
- end
17
-
18
- after_execution :track_metrics
19
-
20
- def call
21
- if cart_abandoned?
22
- skip!(reason: "Cart was abandoned due to 30 days of inactivity")
23
- elsif cart_items_out_of_stock?
24
- fail!(reason: "Items in the cart are out of stock", item: [123, 987])
25
- else
26
- charge_payment_method
27
- ship_order_packages
28
- send_confirmation_email
29
- end
30
- end
31
-
32
- private
33
-
34
- def charge_payment_method
35
- @charge_payment_method ||= ChargePaymentMethodTask.call(details: billing_details)
36
- end
37
-
38
- def ship_order_packages
39
- @ship_order_packages ||= ShipOrderPackagesTask.call(details: shipping_details)
40
- end
41
-
42
- def send_confirmation_email
43
- return if charge_payment_method.failed? || ship_order_packages.bad?
44
-
45
- BatchSendConfirmationNotifications.call(context)
46
- end
47
-
48
- def track_metrics
49
- if Rails.env.development?
50
- logger.debug { "Sending metrics to collector" }
51
- else
52
- TrackMetricsTask.call(metric: :process_order, status: order.status)
53
- end
54
- end
55
-
56
- end
57
- ```
58
-
59
- ## Execution
60
-
61
- ```ruby
62
- class OrdersController < ApplicationController
63
-
64
- def create
65
- task = ProcessOrderTask.call(order_params)
66
-
67
- if task.success?
68
- flash[:success] = "Order is on its way!"
69
- redirect_to(my_orders_path)
70
- else
71
- flash[:error] = "Whoops something is wrong: #{task.metadata[:reason]}"
72
- render(:new)
73
- end
74
- end
75
-
76
- end
77
- ```
78
-
79
- ---
80
-
81
- - **Prev:** [Tips & Tricks](https://github.com/drexed/cmdx/blob/main/docs/tips_and_tricks.md)
82
- - **Next:** [Getting Started](https://github.com/drexed/cmdx/blob/main/docs/getting_started.md)
data/docs/hooks.md DELETED
@@ -1,62 +0,0 @@
1
- # Hooks
2
-
3
- Hooks (callbacks) run logic at task transition points. Callable hooks have access
4
- to all the same information as the `call` method.
5
-
6
- > [!TIP]
7
- > Hooks are inheritable which is handy for setting up global logic execution,
8
- > eg: setting tracking markers, account plan checks, etc.
9
-
10
- ```ruby
11
- class ProcessOrderTask < CMDx::Task
12
-
13
- # Symbol or string declaration:
14
- after_validation :verify_message_starting_chars
15
-
16
- # Proc or lambda declaration:
17
- on_complete -> { send_telemetry_data }
18
-
19
- # Multiple declarations:
20
- on_success :increment_success_task_counter, :scrub_secret_message_data
21
-
22
- # With options (applies to all declared in that group):
23
- on_failure :increment_failure_task_counter, if: :worth_keep_track?
24
-
25
- def call
26
- # Do work...
27
- end
28
-
29
- end
30
- ```
31
-
32
- The hook methods support the following options:
33
-
34
- | Option | Description |
35
- | ------------- | ----------- |
36
- | `:if` | Specifies a callable method, proc or string to determine if hook processing should occur. |
37
- | `:unless` | Specifies a callable method, proc, or string to determine if hook processing should not occur. |
38
-
39
- ## Order
40
-
41
- Hook types are executed in the following order:
42
-
43
- ```ruby
44
- 0. before_execution
45
- 1. on_executing
46
- 2. before_validation
47
- 3. after_validation
48
- 4. on_[complete, interrupted]
49
- 5. on_executed
50
- 6. on_[success, skipped, failed]
51
- 7. on_good
52
- 8. on_bad
53
- 9. after_execution
54
- ```
55
-
56
- > [!IMPORTANT]
57
- > Callable hooks are executed in the order they are declared (FIFO: first in, first out).
58
-
59
- ---
60
-
61
- - **Prev:** [Outcomes - States](https://github.com/drexed/cmdx/blob/main/docs/outcomes/states.md)
62
- - **Next:** [Batch](https://github.com/drexed/cmdx/blob/main/docs/batch.md)
data/lib/cmdx/batch.rb DELETED
@@ -1,43 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module CMDx
4
- class Batch < Task
5
-
6
- Group = Struct.new(:tasks, :options)
7
-
8
- class << self
9
-
10
- def batch_groups
11
- @batch_groups ||= []
12
- end
13
-
14
- def process(*tasks, **options)
15
- batch_groups << Group.new(
16
- tasks.flatten.map do |task|
17
- next task if task <= Task
18
-
19
- raise ArgumentError, "must be a Batch or Task"
20
- end,
21
- options
22
- )
23
- end
24
-
25
- end
26
-
27
- def call
28
- self.class.batch_groups.each do |group|
29
- next unless __cmdx_eval(group.options)
30
-
31
- batch_halt = group.options[:batch_halt] || task_setting(:batch_halt)
32
-
33
- group.tasks.each do |task|
34
- task_result = task.call(context)
35
- next unless Array(batch_halt).include?(task_result.status)
36
-
37
- throw!(task_result)
38
- end
39
- end
40
- end
41
-
42
- end
43
- end
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module CMDx
4
- class Parameters < Array
5
-
6
- def invalid?
7
- !valid?
8
- end
9
-
10
- def valid?
11
- all?(&:valid?)
12
- end
13
-
14
- def validate!(task)
15
- each { |p| recursive_validate!(task, p) }
16
- end
17
-
18
- def to_h
19
- ParametersSerializer.call(self)
20
- end
21
- alias to_a to_h
22
-
23
- def to_s
24
- ParametersInspector.call(self)
25
- end
26
-
27
- private
28
-
29
- def recursive_validate!(task, parameter)
30
- task.send(parameter.method_name)
31
- parameter.children.each { |cp| recursive_validate!(task, cp) }
32
- end
33
-
34
- end
35
- end
data/lib/cmdx/run.rb DELETED
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module CMDx
4
- class Run
5
-
6
- __cmdx_attr_delegator :index, to: :results
7
- __cmdx_attr_delegator :state, :status, :outcome, :runtime, to: :first_result
8
-
9
- attr_reader :id, :results
10
-
11
- def initialize(attributes = {})
12
- @id = attributes[:id] || SecureRandom.uuid
13
- @results = Array(attributes[:results])
14
- end
15
-
16
- def freeze
17
- first_result
18
- super
19
- end
20
-
21
- def to_h
22
- RunSerializer.call(self)
23
- end
24
- alias to_a to_h
25
-
26
- def to_s
27
- RunInspector.call(self)
28
- end
29
-
30
- private
31
-
32
- def first_result
33
- return @first_result if defined?(@first_result)
34
-
35
- @first_result = @results.first
36
- end
37
-
38
- end
39
- end
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module CMDx
4
- module RunInspector
5
-
6
- FOOTER_KEYS = %i[
7
- state status outcome runtime
8
- ].freeze
9
-
10
- module_function
11
-
12
- def call(run)
13
- header = "\nrun: #{run.id}"
14
- footer = FOOTER_KEYS.map { |key| "#{key}: #{run.send(key)}" }.join(" | ")
15
- spacer = "=" * [header.size, footer.size].max
16
-
17
- run
18
- .results
19
- .map { |r| r.to_h.except(:run_id).pretty_inspect }
20
- .unshift(header, "#{spacer}\n")
21
- .push(spacer, "#{footer}\n\n")
22
- .join("\n")
23
- end
24
-
25
- end
26
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module CMDx
4
- module RunSerializer
5
-
6
- module_function
7
-
8
- def call(run)
9
- {
10
- id: run.id,
11
- state: run.state,
12
- status: run.status,
13
- outcome: run.outcome,
14
- runtime: run.runtime,
15
- results: run.results.map(&:to_h)
16
- }
17
- end
18
-
19
- end
20
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module CMDx
4
- module TaskHook
5
-
6
- module_function
7
-
8
- def call(task, hook)
9
- Array(task.class.cmd_hooks[hook]).each do |callables, options|
10
- next unless task.__cmdx_eval(options)
11
-
12
- hooks = Array(callables)
13
- hooks.each { |h| task.__cmdx_try(h) }
14
- end
15
- end
16
-
17
- end
18
- end
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Cmdx
4
- class BatchGenerator < Rails::Generators::NamedBase
5
-
6
- source_root File.expand_path("templates", __dir__)
7
- check_class_collision prefix: "Batch"
8
-
9
- desc "Generates a batch task with the given NAME (if one does not exist)."
10
-
11
- def copy_files
12
- name = file_name.sub(/^batch_?/i, "")
13
- path = File.join("app/cmds", class_path, "batch_#{name}.rb")
14
- template("batch.rb.tt", path)
15
- end
16
-
17
- private
18
-
19
- def class_name
20
- @class_name ||= super.delete_prefix("Batch")
21
- end
22
-
23
- def parent_class_name
24
- ApplicationBatch
25
- rescue StandardError
26
- CMDx::Batch
27
- end
28
-
29
- end
30
- end