cmdx 1.6.2 → 1.7.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/CHANGELOG.md +14 -0
- data/LLM.md +165 -2
- data/docs/internationalization.md +106 -2
- data/docs/outcomes/result.md +17 -0
- data/docs/workflows.md +48 -0
- data/lib/cmdx/pipeline.rb +43 -11
- data/lib/cmdx/task.rb +7 -6
- data/lib/cmdx/version.rb +1 -1
- data/lib/cmdx.rb +2 -0
- data/lib/generators/cmdx/locale_generator.rb +39 -0
- data/lib/generators/cmdx/templates/workflow.rb.tt +8 -0
- data/lib/generators/cmdx/workflow_generator.rb +57 -0
- data/lib/locales/af.yml +49 -0
- data/lib/locales/ar.yml +49 -0
- data/lib/locales/az.yml +49 -0
- data/lib/locales/be.yml +49 -0
- data/lib/locales/bg.yml +49 -0
- data/lib/locales/bn.yml +49 -0
- data/lib/locales/bs.yml +49 -0
- data/lib/locales/ca.yml +49 -0
- data/lib/locales/cnr.yml +49 -0
- data/lib/locales/cs.yml +49 -0
- data/lib/locales/cy.yml +49 -0
- data/lib/locales/da.yml +49 -0
- data/lib/locales/de.yml +49 -0
- data/lib/locales/dz.yml +49 -0
- data/lib/locales/el.yml +49 -0
- data/lib/locales/eo.yml +49 -0
- data/lib/locales/es.yml +49 -0
- data/lib/locales/et.yml +49 -0
- data/lib/locales/eu.yml +49 -0
- data/lib/locales/fa.yml +49 -0
- data/lib/locales/fi.yml +49 -0
- data/lib/locales/fr.yml +49 -0
- data/lib/locales/fy.yml +49 -0
- data/lib/locales/gd.yml +49 -0
- data/lib/locales/gl.yml +49 -0
- data/lib/locales/he.yml +49 -0
- data/lib/locales/hi.yml +49 -0
- data/lib/locales/hr.yml +49 -0
- data/lib/locales/hu.yml +49 -0
- data/lib/locales/hy.yml +49 -0
- data/lib/locales/id.yml +49 -0
- data/lib/locales/is.yml +49 -0
- data/lib/locales/it.yml +49 -0
- data/lib/locales/ja.yml +49 -0
- data/lib/locales/ka.yml +49 -0
- data/lib/locales/kk.yml +49 -0
- data/lib/locales/km.yml +49 -0
- data/lib/locales/kn.yml +49 -0
- data/lib/locales/ko.yml +49 -0
- data/lib/locales/lb.yml +49 -0
- data/lib/locales/lo.yml +49 -0
- data/lib/locales/lt.yml +49 -0
- data/lib/locales/lv.yml +49 -0
- data/lib/locales/mg.yml +49 -0
- data/lib/locales/mk.yml +49 -0
- data/lib/locales/ml.yml +49 -0
- data/lib/locales/mn.yml +49 -0
- data/lib/locales/mr-IN.yml +49 -0
- data/lib/locales/ms.yml +49 -0
- data/lib/locales/nb.yml +49 -0
- data/lib/locales/ne.yml +49 -0
- data/lib/locales/nl.yml +49 -0
- data/lib/locales/nn.yml +49 -0
- data/lib/locales/oc.yml +49 -0
- data/lib/locales/or.yml +49 -0
- data/lib/locales/pa.yml +49 -0
- data/lib/locales/pl.yml +49 -0
- data/lib/locales/pt.yml +49 -0
- data/lib/locales/rm.yml +49 -0
- data/lib/locales/ro.yml +49 -0
- data/lib/locales/ru.yml +49 -0
- data/lib/locales/sc.yml +49 -0
- data/lib/locales/sk.yml +49 -0
- data/lib/locales/sl.yml +49 -0
- data/lib/locales/sq.yml +49 -0
- data/lib/locales/sr.yml +49 -0
- data/lib/locales/st.yml +49 -0
- data/lib/locales/sv.yml +49 -0
- data/lib/locales/sw.yml +49 -0
- data/lib/locales/ta.yml +49 -0
- data/lib/locales/te.yml +49 -0
- data/lib/locales/th.yml +49 -0
- data/lib/locales/tl.yml +49 -0
- data/lib/locales/tr.yml +49 -0
- data/lib/locales/tt.yml +49 -0
- data/lib/locales/ug.yml +49 -0
- data/lib/locales/uk.yml +49 -0
- data/lib/locales/ur.yml +49 -0
- data/lib/locales/uz.yml +49 -0
- data/lib/locales/vi.yml +49 -0
- data/lib/locales/wo.yml +49 -0
- data/lib/locales/zh-CN.yml +49 -0
- data/lib/locales/zh-HK.yml +49 -0
- data/lib/locales/zh-TW.yml +49 -0
- data/lib/locales/zh-YUE.yml +49 -0
- metadata +103 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9bbf1d8db7665b82da9af2dd5e017977945bbd550700177368b1363a8e63275e
|
4
|
+
data.tar.gz: 0f1720432a999ff31399d67c602e5277ee8cb1a8062117165c425a39233eb81c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 144c01abf663258e34b40eaa9e1deba09b59347b97773237f9bd84f5d82474825aca38f21b6ad0c052f1b058f6a5550e24ef8f3598da4cdecad94da1689bea5c
|
7
|
+
data.tar.gz: 25220966f85607b73740107b5af5da7889e75592055ad17156bc48f157550e2d030f542b7f279ec731cbb78ef732be1c6507b8e448a97a8324749d4746549d95
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
|
7
7
|
## [TODO]
|
8
8
|
|
9
|
+
## [1.7.1] - 2025-08-26
|
10
|
+
|
11
|
+
### Added
|
12
|
+
- Yield result if block given to `execute` and `execute!` methods
|
13
|
+
|
14
|
+
## [1.7.0] - 2025-08-25
|
15
|
+
|
16
|
+
### Added
|
17
|
+
- Workflow generator
|
18
|
+
|
19
|
+
### Changes
|
20
|
+
- Port over `cmdx-parallel` changes
|
21
|
+
- Port over `cmdx-i18n` changes
|
22
|
+
|
9
23
|
## [1.6.2] - 2025-08-24
|
10
24
|
|
11
25
|
### Changes
|
data/LLM.md
CHANGED
@@ -1251,6 +1251,22 @@ result.index #=> 0 (first task in chain)
|
|
1251
1251
|
result.chain.results[result.index] == result #=> true
|
1252
1252
|
```
|
1253
1253
|
|
1254
|
+
## Block Yield
|
1255
|
+
|
1256
|
+
Implement conditional logic using a block expression that yields a result for complete encapsulation.
|
1257
|
+
|
1258
|
+
```ruby
|
1259
|
+
BuildApplication.execute(version: "1.2.3") do |result|
|
1260
|
+
if result.success?
|
1261
|
+
notify_deployment_ready(result)
|
1262
|
+
elsif result.failed?
|
1263
|
+
handle_build_failure(result)
|
1264
|
+
else
|
1265
|
+
log_skip_reason(result)
|
1266
|
+
end
|
1267
|
+
end
|
1268
|
+
```
|
1269
|
+
|
1254
1270
|
## Handlers
|
1255
1271
|
|
1256
1272
|
Use result handlers for clean, functional-style conditional logic. Handlers return the result object, enabling method chaining and fluent interfaces.
|
@@ -2830,8 +2846,109 @@ I18n.with_locale(:fr) do
|
|
2830
2846
|
end
|
2831
2847
|
```
|
2832
2848
|
|
2833
|
-
|
2834
|
-
|
2849
|
+
## Configuration
|
2850
|
+
|
2851
|
+
Localization is handled by the `I18n` gem. In Rails applications, locales are loaded automatically and managed via the `I18n.available_locales` setting.
|
2852
|
+
|
2853
|
+
### Local Copies
|
2854
|
+
|
2855
|
+
Execute the following command to copy any locale into the Rails applications `config/locales` directory:
|
2856
|
+
|
2857
|
+
```bash
|
2858
|
+
rails generate cmdx:locale [LOCALE]
|
2859
|
+
|
2860
|
+
# Eg: generate french locale
|
2861
|
+
rails generate cmdx:locale fr
|
2862
|
+
```
|
2863
|
+
|
2864
|
+
### Available Locales
|
2865
|
+
|
2866
|
+
- af - Afrikaans
|
2867
|
+
- ar - Arabic
|
2868
|
+
- az - Azerbaijani
|
2869
|
+
- be - Belarusian
|
2870
|
+
- bg - Bulgarian
|
2871
|
+
- bn - Bengali
|
2872
|
+
- bs - Bosnian
|
2873
|
+
- ca - Catalan
|
2874
|
+
- cnr - Montenegrin
|
2875
|
+
- cs - Czech
|
2876
|
+
- cy - Welsh
|
2877
|
+
- da - Danish
|
2878
|
+
- de - German
|
2879
|
+
- dz - Dzongkha
|
2880
|
+
- el - Greek
|
2881
|
+
- en - English
|
2882
|
+
- eo - Esperanto
|
2883
|
+
- es - Spanish
|
2884
|
+
- et - Estonian
|
2885
|
+
- eu - Basque
|
2886
|
+
- fa - Persian
|
2887
|
+
- fi - Finnish
|
2888
|
+
- fr - French
|
2889
|
+
- fy - Western Frisian
|
2890
|
+
- gd - Scottish Gaelic
|
2891
|
+
- gl - Galician
|
2892
|
+
- he - Hebrew
|
2893
|
+
- hi - Hindi
|
2894
|
+
- hr - Croatian
|
2895
|
+
- hu - Hungarian
|
2896
|
+
- hy - Armenian
|
2897
|
+
- id - Indonesian
|
2898
|
+
- is - Icelandic
|
2899
|
+
- it - Italian
|
2900
|
+
- ja - Japanese
|
2901
|
+
- ka - Georgian
|
2902
|
+
- kk - Kazakh
|
2903
|
+
- km - Khmer
|
2904
|
+
- kn - Kannada
|
2905
|
+
- ko - Korean
|
2906
|
+
- lb - Luxembourgish
|
2907
|
+
- lo - Lao
|
2908
|
+
- lt - Lithuanian
|
2909
|
+
- lv - Latvian
|
2910
|
+
- mg - Malagasy
|
2911
|
+
- mk - Macedonian
|
2912
|
+
- ml - Malayalam
|
2913
|
+
- mn - Mongolian
|
2914
|
+
- mr-IN - Marathi (India)
|
2915
|
+
- ms - Malay
|
2916
|
+
- nb - Norwegian Bokmål
|
2917
|
+
- ne - Nepali
|
2918
|
+
- nl - Dutch
|
2919
|
+
- nn - Norwegian Nynorsk
|
2920
|
+
- oc - Occitan
|
2921
|
+
- or - Odia
|
2922
|
+
- pa - Punjabi
|
2923
|
+
- pl - Polish
|
2924
|
+
- pt - Portuguese
|
2925
|
+
- rm - Romansh
|
2926
|
+
- ro - Romanian
|
2927
|
+
- ru - Russian
|
2928
|
+
- sc - Sardinian
|
2929
|
+
- sk - Slovak
|
2930
|
+
- sl - Slovenian
|
2931
|
+
- sq - Albanian
|
2932
|
+
- sr - Serbian
|
2933
|
+
- st - Southern Sotho
|
2934
|
+
- sv - Swedish
|
2935
|
+
- sw - Swahili
|
2936
|
+
- ta - Tamil
|
2937
|
+
- te - Telugu
|
2938
|
+
- th - Thai
|
2939
|
+
- tl - Tagalog
|
2940
|
+
- tr - Turkish
|
2941
|
+
- tt - Tatar
|
2942
|
+
- ug - Uyghur
|
2943
|
+
- uk - Ukrainian
|
2944
|
+
- ur - Urdu
|
2945
|
+
- uz - Uzbek
|
2946
|
+
- vi - Vietnamese
|
2947
|
+
- wo - Wolof
|
2948
|
+
- zh-CN - Chinese (Simplified)
|
2949
|
+
- zh-HK - Chinese (Hong Kong)
|
2950
|
+
- zh-TW - Chinese (Traditional)
|
2951
|
+
- zh-YUE - Chinese (Yue)
|
2835
2952
|
|
2836
2953
|
---
|
2837
2954
|
|
@@ -3166,6 +3283,52 @@ class CompleteEmailWorkflow < CMDx::Task
|
|
3166
3283
|
end
|
3167
3284
|
```
|
3168
3285
|
|
3286
|
+
## Parallel Execution
|
3287
|
+
|
3288
|
+
Parallel task execution leverages the [Parallel](https://github.com/grosser/parallel) gem, which automatically detects the number of available processors to maximize concurrent task execution.
|
3289
|
+
|
3290
|
+
> [!IMPORTANT]
|
3291
|
+
> Context cannot be modified during parallel execution. Ensure that all required data is preloaded into the context before parallelization begins.
|
3292
|
+
|
3293
|
+
```ruby
|
3294
|
+
class SendWelcomeNotifications < CMDx::Task
|
3295
|
+
include CMDx::Workflow
|
3296
|
+
|
3297
|
+
# Default options (dynamically calculated to available processors)
|
3298
|
+
tasks SendWelcomeEmail, SendWelcomeSms, SendWelcomePush, strategy: :parallel
|
3299
|
+
|
3300
|
+
# Fix number of threads
|
3301
|
+
tasks SendWelcomeEmail, SendWelcomeSms, SendWelcomePush, strategy: :parallel, in_threads: 2
|
3302
|
+
|
3303
|
+
# Fix number of forked processes
|
3304
|
+
tasks SendWelcomeEmail, SendWelcomeSms, SendWelcomePush, strategy: :parallel, in_processes: 2
|
3305
|
+
|
3306
|
+
# NOTE: Reactors are not supported
|
3307
|
+
end
|
3308
|
+
```
|
3309
|
+
|
3310
|
+
## Task Generator
|
3311
|
+
|
3312
|
+
Generate new CMDx workflow tasks quickly using the built-in generator:
|
3313
|
+
|
3314
|
+
```bash
|
3315
|
+
rails generate cmdx:workflow SendNotifications
|
3316
|
+
```
|
3317
|
+
|
3318
|
+
This creates a new workflow task file with the basic structure:
|
3319
|
+
|
3320
|
+
```ruby
|
3321
|
+
# app/tasks/send_notifications.rb
|
3322
|
+
class SendNotifications < CMDx::Task
|
3323
|
+
include CMDx::Workflow
|
3324
|
+
|
3325
|
+
tasks Task1, Task2
|
3326
|
+
end
|
3327
|
+
```
|
3328
|
+
|
3329
|
+
> [!TIP]
|
3330
|
+
> Use **present tense verbs + pluralized noun** for workflow task names, eg: `SendNotifications`, `DownloadFiles`, `ValidateDocuments`
|
3331
|
+
|
3169
3332
|
---
|
3170
3333
|
|
3171
3334
|
url: https://github.com/drexed/cmdx/blob/main/docs/tips_and_tricks.md
|
@@ -5,6 +5,9 @@ CMDx provides comprehensive internationalization support for all error messages,
|
|
5
5
|
## Table of Contents
|
6
6
|
|
7
7
|
- [Localization](#localization)
|
8
|
+
- [Configuration](#configuration)
|
9
|
+
- [Local Copies](#local-copies)
|
10
|
+
- [Available Locales](#available-locales)
|
8
11
|
|
9
12
|
## Localization
|
10
13
|
|
@@ -25,8 +28,109 @@ I18n.with_locale(:fr) do
|
|
25
28
|
end
|
26
29
|
```
|
27
30
|
|
28
|
-
|
29
|
-
|
31
|
+
## Configuration
|
32
|
+
|
33
|
+
Localization is handled by the `I18n` gem. In Rails applications, locales are loaded automatically and managed via the `I18n.available_locales` setting.
|
34
|
+
|
35
|
+
### Local Copies
|
36
|
+
|
37
|
+
Execute the following command to copy any locale into the Rails applications `config/locales` directory:
|
38
|
+
|
39
|
+
```bash
|
40
|
+
rails generate cmdx:locale [LOCALE]
|
41
|
+
|
42
|
+
# Eg: generate french locale
|
43
|
+
rails generate cmdx:locale fr
|
44
|
+
```
|
45
|
+
|
46
|
+
### Available Locales
|
47
|
+
|
48
|
+
- af - Afrikaans
|
49
|
+
- ar - Arabic
|
50
|
+
- az - Azerbaijani
|
51
|
+
- be - Belarusian
|
52
|
+
- bg - Bulgarian
|
53
|
+
- bn - Bengali
|
54
|
+
- bs - Bosnian
|
55
|
+
- ca - Catalan
|
56
|
+
- cnr - Montenegrin
|
57
|
+
- cs - Czech
|
58
|
+
- cy - Welsh
|
59
|
+
- da - Danish
|
60
|
+
- de - German
|
61
|
+
- dz - Dzongkha
|
62
|
+
- el - Greek
|
63
|
+
- en - English
|
64
|
+
- eo - Esperanto
|
65
|
+
- es - Spanish
|
66
|
+
- et - Estonian
|
67
|
+
- eu - Basque
|
68
|
+
- fa - Persian
|
69
|
+
- fi - Finnish
|
70
|
+
- fr - French
|
71
|
+
- fy - Western Frisian
|
72
|
+
- gd - Scottish Gaelic
|
73
|
+
- gl - Galician
|
74
|
+
- he - Hebrew
|
75
|
+
- hi - Hindi
|
76
|
+
- hr - Croatian
|
77
|
+
- hu - Hungarian
|
78
|
+
- hy - Armenian
|
79
|
+
- id - Indonesian
|
80
|
+
- is - Icelandic
|
81
|
+
- it - Italian
|
82
|
+
- ja - Japanese
|
83
|
+
- ka - Georgian
|
84
|
+
- kk - Kazakh
|
85
|
+
- km - Khmer
|
86
|
+
- kn - Kannada
|
87
|
+
- ko - Korean
|
88
|
+
- lb - Luxembourgish
|
89
|
+
- lo - Lao
|
90
|
+
- lt - Lithuanian
|
91
|
+
- lv - Latvian
|
92
|
+
- mg - Malagasy
|
93
|
+
- mk - Macedonian
|
94
|
+
- ml - Malayalam
|
95
|
+
- mn - Mongolian
|
96
|
+
- mr-IN - Marathi (India)
|
97
|
+
- ms - Malay
|
98
|
+
- nb - Norwegian Bokmål
|
99
|
+
- ne - Nepali
|
100
|
+
- nl - Dutch
|
101
|
+
- nn - Norwegian Nynorsk
|
102
|
+
- oc - Occitan
|
103
|
+
- or - Odia
|
104
|
+
- pa - Punjabi
|
105
|
+
- pl - Polish
|
106
|
+
- pt - Portuguese
|
107
|
+
- rm - Romansh
|
108
|
+
- ro - Romanian
|
109
|
+
- ru - Russian
|
110
|
+
- sc - Sardinian
|
111
|
+
- sk - Slovak
|
112
|
+
- sl - Slovenian
|
113
|
+
- sq - Albanian
|
114
|
+
- sr - Serbian
|
115
|
+
- st - Southern Sotho
|
116
|
+
- sv - Swedish
|
117
|
+
- sw - Swahili
|
118
|
+
- ta - Tamil
|
119
|
+
- te - Telugu
|
120
|
+
- th - Thai
|
121
|
+
- tl - Tagalog
|
122
|
+
- tr - Turkish
|
123
|
+
- tt - Tatar
|
124
|
+
- ug - Uyghur
|
125
|
+
- uk - Ukrainian
|
126
|
+
- ur - Urdu
|
127
|
+
- uz - Uzbek
|
128
|
+
- vi - Vietnamese
|
129
|
+
- wo - Wolof
|
130
|
+
- zh-CN - Chinese (Simplified)
|
131
|
+
- zh-HK - Chinese (Hong Kong)
|
132
|
+
- zh-TW - Chinese (Traditional)
|
133
|
+
- zh-YUE - Chinese (Yue)
|
30
134
|
|
31
135
|
---
|
32
136
|
|
data/docs/outcomes/result.md
CHANGED
@@ -9,6 +9,7 @@ The result object is the comprehensive return value of task execution, providing
|
|
9
9
|
- [Outcome Analysis](#outcome-analysis)
|
10
10
|
- [Chain Analysis](#chain-analysis)
|
11
11
|
- [Index and Position](#index-and-position)
|
12
|
+
- [Block Yield](#block-yield)
|
12
13
|
- [Handlers](#handlers)
|
13
14
|
- [Pattern Matching](#pattern-matching)
|
14
15
|
- [Array Pattern](#array-pattern)
|
@@ -113,6 +114,22 @@ result.index #=> 0 (first task in chain)
|
|
113
114
|
result.chain.results[result.index] == result #=> true
|
114
115
|
```
|
115
116
|
|
117
|
+
## Block Yield
|
118
|
+
|
119
|
+
Implement conditional logic using a block expression that yields a result for complete encapsulation.
|
120
|
+
|
121
|
+
```ruby
|
122
|
+
BuildApplication.execute(version: "1.2.3") do |result|
|
123
|
+
if result.success?
|
124
|
+
notify_deployment_ready(result)
|
125
|
+
elsif result.failed?
|
126
|
+
handle_build_failure(result)
|
127
|
+
else
|
128
|
+
log_skip_reason(result)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
```
|
132
|
+
|
116
133
|
## Handlers
|
117
134
|
|
118
135
|
Use result handlers for clean, functional-style conditional logic. Handlers return the result object, enabling method chaining and fluent interfaces.
|
data/docs/workflows.md
CHANGED
@@ -12,6 +12,8 @@ Workflow orchestrates sequential execution of multiple tasks in a linear pipelin
|
|
12
12
|
- [Task Configuration](#task-configuration)
|
13
13
|
- [Group Configuration](#group-configuration)
|
14
14
|
- [Nested Workflows](#nested-workflows)
|
15
|
+
- [Parallel Execution](#parallel-execution)
|
16
|
+
- [Task Generator](#task-generator)
|
15
17
|
|
16
18
|
## Declarations
|
17
19
|
|
@@ -187,6 +189,52 @@ class CompleteEmailWorkflow < CMDx::Task
|
|
187
189
|
end
|
188
190
|
```
|
189
191
|
|
192
|
+
## Parallel Execution
|
193
|
+
|
194
|
+
Parallel task execution leverages the [Parallel](https://github.com/grosser/parallel) gem, which automatically detects the number of available processors to maximize concurrent task execution.
|
195
|
+
|
196
|
+
> [!IMPORTANT]
|
197
|
+
> Context cannot be modified during parallel execution. Ensure that all required data is preloaded into the context before parallelization begins.
|
198
|
+
|
199
|
+
```ruby
|
200
|
+
class SendWelcomeNotifications < CMDx::Task
|
201
|
+
include CMDx::Workflow
|
202
|
+
|
203
|
+
# Default options (dynamically calculated to available processors)
|
204
|
+
tasks SendWelcomeEmail, SendWelcomeSms, SendWelcomePush, strategy: :parallel
|
205
|
+
|
206
|
+
# Fix number of threads
|
207
|
+
tasks SendWelcomeEmail, SendWelcomeSms, SendWelcomePush, strategy: :parallel, in_threads: 2
|
208
|
+
|
209
|
+
# Fix number of forked processes
|
210
|
+
tasks SendWelcomeEmail, SendWelcomeSms, SendWelcomePush, strategy: :parallel, in_processes: 2
|
211
|
+
|
212
|
+
# NOTE: Reactors are not supported
|
213
|
+
end
|
214
|
+
```
|
215
|
+
|
216
|
+
## Task Generator
|
217
|
+
|
218
|
+
Generate new CMDx workflow tasks quickly using the built-in generator:
|
219
|
+
|
220
|
+
```bash
|
221
|
+
rails generate cmdx:workflow SendNotifications
|
222
|
+
```
|
223
|
+
|
224
|
+
This creates a new workflow task file with the basic structure:
|
225
|
+
|
226
|
+
```ruby
|
227
|
+
# app/tasks/send_notifications.rb
|
228
|
+
class SendNotifications < CMDx::Task
|
229
|
+
include CMDx::Workflow
|
230
|
+
|
231
|
+
tasks Task1, Task2
|
232
|
+
end
|
233
|
+
```
|
234
|
+
|
235
|
+
> [!TIP]
|
236
|
+
> Use **present tense verbs + pluralized noun** for workflow task names, eg: `SendNotifications`, `DownloadFiles`, `ValidateDocuments`
|
237
|
+
|
190
238
|
---
|
191
239
|
|
192
240
|
- **Prev:** [Deprecation](deprecation.md)
|
data/lib/cmdx/pipeline.rb
CHANGED
@@ -55,23 +55,22 @@ module CMDx
|
|
55
55
|
|
56
56
|
private
|
57
57
|
|
58
|
-
# Executes
|
59
|
-
# Override this method to implement custom execution strategies like parallel
|
60
|
-
# processing or conditional task execution.
|
58
|
+
# Executes a group of tasks using the specified execution strategy.
|
61
59
|
#
|
62
|
-
# @param group [
|
63
|
-
# @param breakpoints [Array<
|
60
|
+
# @param group [CMDx::Group] The task group to execute
|
61
|
+
# @param breakpoints [Array<Symbol>] Status values that trigger execution breaks
|
62
|
+
# @option group.options [Symbol, String] :strategy Execution strategy (:sequential, :parallel, or nil for default)
|
64
63
|
#
|
65
64
|
# @return [void]
|
66
65
|
#
|
67
66
|
# @example
|
68
|
-
#
|
69
|
-
# # Custom parallel execution strategy
|
70
|
-
# group.tasks.map { |task| Thread.new { task.execute(workflow.context) } }
|
71
|
-
# end
|
67
|
+
# execute_group_tasks(group, ["failed", "skipped"])
|
72
68
|
def execute_group_tasks(group, breakpoints)
|
73
|
-
|
74
|
-
execute_tasks_in_sequence(group, breakpoints)
|
69
|
+
case strategy = group.options[:strategy]
|
70
|
+
when NilClass, /sequential/ then execute_tasks_in_sequence(group, breakpoints)
|
71
|
+
when /parallel/ then execute_tasks_in_parallel(group, breakpoints)
|
72
|
+
else raise "unknown execution strategy #{strategy.inspect}"
|
73
|
+
end
|
75
74
|
end
|
76
75
|
|
77
76
|
# Executes tasks sequentially within a group, checking breakpoints after each task.
|
@@ -95,5 +94,38 @@ module CMDx
|
|
95
94
|
end
|
96
95
|
end
|
97
96
|
|
97
|
+
# Executes tasks in parallel using the parallel gem.
|
98
|
+
#
|
99
|
+
# @param group [CMDx::Group] The task group to execute in parallel
|
100
|
+
# @param breakpoints [Array<Symbol>] Status values that trigger execution breaks
|
101
|
+
# @option group.options [Integer] :in_threads Number of threads to use
|
102
|
+
# @option group.options [Integer] :in_processes Number of processes to use
|
103
|
+
#
|
104
|
+
# @return [void]
|
105
|
+
#
|
106
|
+
# @raise [HaltError] When a task result status matches a breakpoint
|
107
|
+
#
|
108
|
+
# @example
|
109
|
+
# execute_tasks_in_parallel(group, ["failed"])
|
110
|
+
def execute_tasks_in_parallel(group, breakpoints)
|
111
|
+
raise "install the `parallel` gem to use this feature" unless defined?(::Parallel)
|
112
|
+
|
113
|
+
parallel_options = group.options.slice(:in_threads, :in_processes)
|
114
|
+
throwable_result = nil
|
115
|
+
|
116
|
+
::Parallel.each(group.tasks, **parallel_options) do |task|
|
117
|
+
Chain.current = workflow.chain
|
118
|
+
|
119
|
+
task_result = task.execute(workflow.context)
|
120
|
+
next unless breakpoints.include?(task_result.status)
|
121
|
+
|
122
|
+
raise ::Parallel::Break, throwable_result = task_result
|
123
|
+
end
|
124
|
+
|
125
|
+
return if throwable_result.nil?
|
126
|
+
|
127
|
+
workflow.throw!(throwable_result)
|
128
|
+
end
|
129
|
+
|
98
130
|
end
|
99
131
|
end
|
data/lib/cmdx/task.rb
CHANGED
@@ -169,10 +169,10 @@ module CMDx
|
|
169
169
|
# if result.success?
|
170
170
|
# puts "Task completed successfully"
|
171
171
|
# end
|
172
|
-
def execute(
|
173
|
-
task = new(
|
172
|
+
def execute(*args, **kwargs)
|
173
|
+
task = new(*args, **kwargs)
|
174
174
|
task.execute(raise: false)
|
175
|
-
task.result
|
175
|
+
block_given? ? yield(task.result) : task.result
|
176
176
|
end
|
177
177
|
|
178
178
|
# @param args [Array] Arguments to pass to the task constructor
|
@@ -184,10 +184,10 @@ module CMDx
|
|
184
184
|
# @example
|
185
185
|
# result = MyTask.execute!(name: "example")
|
186
186
|
# # Will raise an exception if execution fails
|
187
|
-
def execute!(
|
188
|
-
task = new(
|
187
|
+
def execute!(*args, **kwargs)
|
188
|
+
task = new(*args, **kwargs)
|
189
189
|
task.execute(raise: true)
|
190
|
-
task.result
|
190
|
+
block_given? ? yield(task.result) : task.result
|
191
191
|
end
|
192
192
|
|
193
193
|
end
|
@@ -201,6 +201,7 @@ module CMDx
|
|
201
201
|
# result = task.execute(raise: true)
|
202
202
|
def execute(raise: false)
|
203
203
|
Executor.execute(self, raise:)
|
204
|
+
block_given? ? yield(result) : result
|
204
205
|
end
|
205
206
|
|
206
207
|
# @raise [UndefinedMethodError] Always raised as this method must be overridden
|
data/lib/cmdx/version.rb
CHANGED
data/lib/cmdx.rb
CHANGED
@@ -48,7 +48,9 @@ require_relative "cmdx/faults"
|
|
48
48
|
# Conditionally load Rails components if Rails is available
|
49
49
|
if defined?(Rails::Generators)
|
50
50
|
require_relative "generators/cmdx/install_generator"
|
51
|
+
require_relative "generators/cmdx/locale_generator"
|
51
52
|
require_relative "generators/cmdx/task_generator"
|
53
|
+
require_relative "generators/cmdx/workflow_generator"
|
52
54
|
end
|
53
55
|
|
54
56
|
# Load the Railtie last after everything else is required so we don't
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cmdx
|
4
|
+
# Generates CMDx locale files for Rails applications
|
5
|
+
#
|
6
|
+
# Rails generator that copies CMDx locale files into the application's
|
7
|
+
# config/locales directory. This allows applications to customize and extend
|
8
|
+
# the default CMDx locale files.
|
9
|
+
class LocaleGenerator < Rails::Generators::Base
|
10
|
+
|
11
|
+
source_root File.expand_path("../../locales", __dir__)
|
12
|
+
|
13
|
+
desc "Copies the locale with the given alpha-2 code"
|
14
|
+
|
15
|
+
argument :locale, type: :string, default: "en", banner: "locale: en, es, fr, etc"
|
16
|
+
|
17
|
+
# Copies the locale template to the Rails application
|
18
|
+
#
|
19
|
+
# Copies the specified locale file from the gem's locales directory to the
|
20
|
+
# application's config/locales directory. If the locale file doesn't exist
|
21
|
+
# in the gem, the generator will fail gracefully.
|
22
|
+
#
|
23
|
+
# @return [void]
|
24
|
+
#
|
25
|
+
# @example
|
26
|
+
# # Copy default (English) locale file
|
27
|
+
# rails generate cmdx:locale
|
28
|
+
# # => Creates config/locales/en.yml
|
29
|
+
#
|
30
|
+
# # Copy Spanish locale file
|
31
|
+
# rails generate cmdx:locale es
|
32
|
+
# # => Creates config/locales/es.yml
|
33
|
+
#
|
34
|
+
def copy_locale_files
|
35
|
+
copy_file("#{locale}.yml", "config/locales/#{locale}.yml")
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cmdx
|
4
|
+
# Generates CMDx workflow files for Rails applications
|
5
|
+
#
|
6
|
+
# This generator creates task classes that inherit from either ApplicationTask
|
7
|
+
# (if defined) or CMDx::Task. It generates the task file in the standard
|
8
|
+
# Rails tasks directory structure.
|
9
|
+
class WorkflowGenerator < Rails::Generators::NamedBase
|
10
|
+
|
11
|
+
source_root File.expand_path("templates", __dir__)
|
12
|
+
|
13
|
+
desc "Creates a workflow with the given NAME"
|
14
|
+
|
15
|
+
# Copies the task template to the Rails application
|
16
|
+
#
|
17
|
+
# Creates a new task file at `app/tasks/[class_path]/[file_name].rb` using
|
18
|
+
# the task template. The file is placed in the standard Rails tasks directory
|
19
|
+
# structure, maintaining proper namespacing if the task is nested.
|
20
|
+
#
|
21
|
+
# @return [void]
|
22
|
+
#
|
23
|
+
# @example Basic usage
|
24
|
+
# rails generate cmdx:workflow SendNotifications
|
25
|
+
# # => Creates app/tasks/send_notifications.rb
|
26
|
+
#
|
27
|
+
# @example Nested task
|
28
|
+
# rails generate cmdx:workflow Admin::SendNotifications
|
29
|
+
# # => Creates app/tasks/admin/send_notifications.rb
|
30
|
+
def copy_files
|
31
|
+
path = File.join("app/tasks", class_path, "#{file_name}.rb")
|
32
|
+
template("workflow.rb.tt", path)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# Determines the appropriate parent class name for the generated task
|
38
|
+
#
|
39
|
+
# Attempts to use ApplicationTask if it exists in the application, otherwise
|
40
|
+
# falls back to CMDx::Task. This allows applications to define their own
|
41
|
+
# base task class while maintaining compatibility.
|
42
|
+
#
|
43
|
+
# @return [Class] The parent class for the generated task
|
44
|
+
#
|
45
|
+
# @example
|
46
|
+
# parent_class_name # => ApplicationTask
|
47
|
+
#
|
48
|
+
# @example Fallback behavior
|
49
|
+
# parent_class_name # => CMDx::Task
|
50
|
+
def parent_class_name
|
51
|
+
ApplicationTask
|
52
|
+
rescue NameError
|
53
|
+
CMDx::Task
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|