cmdx 1.7.1 → 1.7.2

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: 9bbf1d8db7665b82da9af2dd5e017977945bbd550700177368b1363a8e63275e
4
- data.tar.gz: 0f1720432a999ff31399d67c602e5277ee8cb1a8062117165c425a39233eb81c
3
+ metadata.gz: 528f3b3b1d4f23045a295cc15c05106c3bd0f9efde6400bb88c01bb2a6455637
4
+ data.tar.gz: 473ca317fd214b48e4e4988ba4358bdcff4a3fc9f9805300dba292f4401e51c1
5
5
  SHA512:
6
- metadata.gz: 144c01abf663258e34b40eaa9e1deba09b59347b97773237f9bd84f5d82474825aca38f21b6ad0c052f1b058f6a5550e24ef8f3598da4cdecad94da1689bea5c
7
- data.tar.gz: 25220966f85607b73740107b5af5da7889e75592055ad17156bc48f157550e2d030f542b7f279ec731cbb78ef732be1c6507b8e448a97a8324749d4746549d95
6
+ metadata.gz: 5b48be81fa184343f76c1891a3b87c25853e0dc859764dbf92946c7b31d69fd4af85b75eee7720470e29949edb395bce668343dbc6b17916079ba9befd1fbc80
7
+ data.tar.gz: b95fe96f12cf2aeb724782808d80b4ee36e083d0f6c60876edac45a6046c7925437f329dc2f98a42432b4794996c3269f71ba7f93452f161a38f365c6d40afa6
data/CHANGELOG.md CHANGED
@@ -6,6 +6,11 @@ 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.2] - 2025-09-03
10
+
11
+ ### Changes
12
+ - Correlation ID is set before continuing to further steps
13
+
9
14
  ## [1.7.1] - 2025-08-26
10
15
 
11
16
  ### Added
data/LLM.md CHANGED
@@ -11,6 +11,31 @@ url: https://github.com/drexed/cmdx/blob/main/docs/getting_started.md
11
11
 
12
12
  CMDx is a Ruby framework for building maintainable, observable business logic through composable command objects. Design robust workflows with automatic attribute validation, structured error handling, comprehensive logging, and intelligent execution flow control.
13
13
 
14
+ **Common Challenges:**
15
+
16
+ - Inconsistent patterns across implementations
17
+ - Minimal or no logging, making debugging painful
18
+ - Fragile designs that erode developer confidence
19
+
20
+ **CMDx Solutions:**
21
+
22
+ - Establishes a consistent, standardized design
23
+ - Provides flow control and error handling
24
+ - Supports composable, reusable workflows
25
+ - Includes detailed logging for observability
26
+ - Defines input attributes with fallback defaults
27
+ - Adds validations and type coercions
28
+ - Plus many other developer-friendly tools
29
+
30
+ ## Compose, Execute, React, Observe pattern
31
+
32
+ CMDx encourages breaking business logic into composable tasks. Each task can be combined into larger workflows, executed with standardized flow control, and fully observed through logging, validations, and context.
33
+
34
+ - **Compose** → Define small, contract-driven tasks with typed attributes, validations, and natural workflow composition.
35
+ - **Execute** → Run tasks with clear outcomes, intentional halts, and pluggable behaviors via middlewares and callbacks.
36
+ - **React** → Adapt to outcomes by chaining follow-up tasks, handling faults, or shaping future flows.
37
+ - **Observe** → Capture immutable results, structured logs, and full execution chains for reliable tracing and insight.
38
+
14
39
  ## Installation
15
40
 
16
41
  Add CMDx to your Gemfile:
@@ -2743,21 +2768,19 @@ Sample output:
2743
2768
  ```log
2744
2769
  <!-- Success (INFO level) -->
2745
2770
  I, [2022-07-17T18:43:15.000000 #3784] INFO -- GenerateInvoice:
2746
- index=0 chain_id="018c2b95-b764-7615-a924-cc5b910ed1e5" type="Task"
2747
- class="GenerateInvoice" state="complete" status="success" metadata={runtime: 187}
2771
+ index=0 chain_id="018c2b95-b764-7615-a924-cc5b910ed1e5" type="Task" class="GenerateInvoice" state="complete" status="success" metadata={runtime: 187}
2748
2772
 
2749
2773
  <!-- Skipped (WARN level) -->
2750
2774
  W, [2022-07-17T18:43:15.000000 #3784] WARN -- ValidateCustomer:
2751
- index=1 state="interrupted" status="skipped" reason="Customer already validated"
2775
+ index=1 chain_id="018c2b95-b764-7615-a924-cc5b910ed1e5" type="Task" class="ValidateCustomer" state="interrupted" status="skipped" reason="Customer already validated"
2752
2776
 
2753
2777
  <!-- Failed (ERROR level) -->
2754
2778
  E, [2022-07-17T18:43:15.000000 #3784] ERROR -- CalculateTax:
2755
- index=2 state="interrupted" status="failed" metadata={error_code: "TAX_SERVICE_UNAVAILABLE"}
2779
+ index=2 chain_id="018c2b95-b764-7615-a924-cc5b910ed1e5" type="Task" class="CalculateTax" state="interrupted" status="failed" metadata={error_code: "TAX_SERVICE_UNAVAILABLE"}
2756
2780
 
2757
2781
  <!-- Failed Chain -->
2758
2782
  E, [2022-07-17T18:43:15.000000 #3784] ERROR -- BillingWorkflow:
2759
- caused_failure={index: 2, class: "CalculateTax", status: "failed"}
2760
- threw_failure={index: 1, class: "ValidateCustomer", status: "failed"}
2783
+ index=3 chain_id="018c2b95-b764-7615-a924-cc5b910ed1e5" type="Task" class="BillingWorkflow" state="interrupted" status="failed" caused_failure={index: 2, class: "CalculateTax", status: "failed"} threw_failure={index: 1, class: "ValidateCustomer", status: "failed"}
2761
2784
  ```
2762
2785
 
2763
2786
  > [!TIP]
data/README.md CHANGED
@@ -8,16 +8,24 @@
8
8
  <img alt="License" src="https://img.shields.io/github/license/drexed/cmdx">
9
9
  </p>
10
10
 
11
- # CMDx
11
+ # 🚀 CMDx — Business logic without the chaos
12
12
 
13
- CMDx is a framework for building maintainable business processes. It simplifies building task objects by offering integrated:
13
+ Stop wrestling with messy service objects. CMDx gives you a clean, consistent way to design business processes:
14
14
 
15
- - Flow controls
16
- - Composable workflows
17
- - Comprehensive logging
18
- - Attribute definition
19
- - Validations and coercions
20
- - And much more...
15
+ - Start small with a single `work` method
16
+ - Scale to complex tasks and multi-step workflows
17
+ - Get built-in flow control, logging, validations, and more...
18
+
19
+ *Build faster. Debug easier. Stay sane.*
20
+
21
+ ## Compose, Execute, React, Observe pattern
22
+
23
+ CMDx encourages breaking business logic into composable tasks. Each task can be combined into larger workflows, executed with standardized flow control, and fully observed through logging, validations, and context.
24
+
25
+ - **Compose** → Define small, contract-driven tasks with typed attributes, validations, and natural workflow composition.
26
+ - **Execute** → Run tasks with clear outcomes, intentional halts, and pluggable behaviors via middlewares and callbacks.
27
+ - **React** → Adapt to outcomes by chaining follow-up tasks, handling faults, or shaping future flows.
28
+ - **Observe** → Capture immutable results, structured logs, and full execution chains for reliable tracing and insight.
21
29
 
22
30
  ## Installation
23
31
 
@@ -37,11 +45,24 @@ Or install it yourself as:
37
45
 
38
46
  ## Quick Example
39
47
 
40
- Here's how a quick 3 step process can open up a world of possibilities:
48
+ Here's how a quick 4 step process can open up a world of possibilities:
49
+
50
+ ### 1. Compose
51
+
52
+ #### Minimum Viable Task
53
+
54
+ ```ruby
55
+ class SendAnalyzedEmail < CMDx::Task
56
+ def work
57
+ user = User.find(context.user_id)
58
+ MetricsMailer.analyzed(user).deliver_now
59
+ end
60
+ end
61
+ ```
62
+
63
+ #### Fully Featured Task
41
64
 
42
65
  ```ruby
43
- # 1. Setup task
44
- # ---------------------------------
45
66
  class AnalyzeMetrics < CMDx::Task
46
67
  register :middleware, CMDx::Middlewares::Correlate, id: -> { Current.request_id }
47
68
 
@@ -56,8 +77,10 @@ class AnalyzeMetrics < CMDx::Task
56
77
  elsif dataset.unprocessed?
57
78
  skip!("Dataset not ready for analysis")
58
79
  else
59
- context.result = PValueAnalyzer.analyze(dataset, analysis_type)
80
+ context.result = PValueAnalyzer.execute(dataset:, analysis_type:)
60
81
  context.analyzed_at = Time.now
82
+
83
+ SendAnalyzedEmail.execute(user_id: Current.account.manager_id)
61
84
  end
62
85
  end
63
86
 
@@ -71,16 +94,20 @@ class AnalyzeMetrics < CMDx::Task
71
94
  dataset.update!(analysis_result_id: context.result.id)
72
95
  end
73
96
  end
97
+ ```
74
98
 
75
- # 2. Execute task
76
- # ---------------------------------
99
+ ### 2. Execute
100
+
101
+ ```ruby
77
102
  result = AnalyzeMetrics.execute(
78
103
  dataset_id: 123,
79
104
  "analysis_type" => "advanced"
80
105
  )
106
+ ```
81
107
 
82
- # 3. Handle result
83
- # ---------------------------------
108
+ ### 3. React
109
+
110
+ ```ruby
84
111
  if result.success?
85
112
  puts "Metrics analyzed at #{result.context.analyzed_at}"
86
113
  elsif result.skipped?
@@ -90,6 +117,16 @@ elsif result.failed?
90
117
  end
91
118
  ```
92
119
 
120
+ ### 4. Observe
121
+
122
+ ```log
123
+ I, [2022-07-17T18:42:37.000000 #3784] INFO -- CMDx:
124
+ index=1 chain_id="018c2b95-23j4-2kj3-32kj-3n4jk3n4jknf" type="Task" class="SendAnalyzedEmail" state="complete" status="success" metadata={runtime: 347}
125
+
126
+ I, [2022-07-17T18:43:15.000000 #3784] INFO -- CMDx:
127
+ index=0 chain_id="018c2b95-b764-7615-a924-cc5b910ed1e5" type="Task" class="AnalyzeMetrics" state="complete" status="success" metadata={runtime: 187}
128
+ ```
129
+
93
130
  ## Table of contents
94
131
 
95
132
  - [Getting Started](docs/getting_started.md)
@@ -122,12 +159,12 @@ end
122
159
 
123
160
  ## Ecosystem
124
161
 
125
- - [cmdx-i18n](https://github.com/drexed/cmdx-i18n) - 85+ translations
126
- - [cmdx-parallel](https://github.com/drexed/cmdx-parallel) - Parallel workflow tasks
162
+ - [cmdx-rspec](https://github.com/drexed/cmdx-rspec) - RSpec test matchers
127
163
 
128
- The following gems are currently under development:
164
+ For backwards compatibility of certain functionality:
129
165
 
130
- - `cmdx-testing` - RSpec and Minitest matchers
166
+ - [cmdx-i18n](https://github.com/drexed/cmdx-i18n) - 85+ translations, `v1.5.0` - `v1.6.2`
167
+ - [cmdx-parallel](https://github.com/drexed/cmdx-parallel) - Parallel workflow tasks, `v1.6.1` - `v1.6.2`
131
168
 
132
169
  ## Development
133
170
 
@@ -2,8 +2,25 @@
2
2
 
3
3
  CMDx is a Ruby framework for building maintainable, observable business logic through composable command objects. Design robust workflows with automatic attribute validation, structured error handling, comprehensive logging, and intelligent execution flow control.
4
4
 
5
+ **Common Challenges:**
6
+
7
+ - Inconsistent patterns across implementations
8
+ - Minimal or no logging, making debugging painful
9
+ - Fragile designs that erode developer confidence
10
+
11
+ **CMDx Solutions:**
12
+
13
+ - Establishes a consistent, standardized design
14
+ - Provides flow control and error handling
15
+ - Supports composable, reusable workflows
16
+ - Includes detailed logging for observability
17
+ - Defines input attributes with fallback defaults
18
+ - Adds validations and type coercions
19
+ - Plus many other developer-friendly tools
20
+
5
21
  ## Table of Contents
6
22
 
23
+ - [Compose, Execute, React, Observe pattern](#compose-execute-react-observe-pattern)
7
24
  - [Installation](#installation)
8
25
  - [Configuration Hierarchy](#configuration-hierarchy)
9
26
  - [Global Configuration](#global-configuration)
@@ -21,6 +38,15 @@ CMDx is a Ruby framework for building maintainable, observable business logic th
21
38
  - [Resetting](#resetting)
22
39
  - [Task Generator](#task-generator)
23
40
 
41
+ ## Compose, Execute, React, Observe pattern
42
+
43
+ CMDx encourages breaking business logic into composable tasks. Each task can be combined into larger workflows, executed with standardized flow control, and fully observed through logging, validations, and context.
44
+
45
+ - *Compose* → Define small, contract-driven tasks with typed attributes, validations, and natural workflow composition.
46
+ - *Execute* → Run tasks with clear outcomes, intentional halts, and pluggable behaviors via middlewares and callbacks.
47
+ - *React* → Adapt to outcomes by chaining follow-up tasks, handling faults, or shaping future flows.
48
+ - *Observe* → Capture immutable results, structured logs, and full execution chains for reliable tracing and insight.
49
+
24
50
  ## Installation
25
51
 
26
52
  Add CMDx to your Gemfile:
data/docs/logging.md CHANGED
@@ -25,21 +25,19 @@ Sample output:
25
25
  ```log
26
26
  <!-- Success (INFO level) -->
27
27
  I, [2022-07-17T18:43:15.000000 #3784] INFO -- GenerateInvoice:
28
- index=0 chain_id="018c2b95-b764-7615-a924-cc5b910ed1e5" type="Task"
29
- class="GenerateInvoice" state="complete" status="success" metadata={runtime: 187}
28
+ index=0 chain_id="018c2b95-b764-7615-a924-cc5b910ed1e5" type="Task" class="GenerateInvoice" state="complete" status="success" metadata={runtime: 187}
30
29
 
31
30
  <!-- Skipped (WARN level) -->
32
31
  W, [2022-07-17T18:43:15.000000 #3784] WARN -- ValidateCustomer:
33
- index=1 state="interrupted" status="skipped" reason="Customer already validated"
32
+ index=1 chain_id="018c2b95-b764-7615-a924-cc5b910ed1e5" type="Task" class="ValidateCustomer" state="interrupted" status="skipped" reason="Customer already validated"
34
33
 
35
34
  <!-- Failed (ERROR level) -->
36
35
  E, [2022-07-17T18:43:15.000000 #3784] ERROR -- CalculateTax:
37
- index=2 state="interrupted" status="failed" metadata={error_code: "TAX_SERVICE_UNAVAILABLE"}
36
+ index=2 chain_id="018c2b95-b764-7615-a924-cc5b910ed1e5" type="Task" class="CalculateTax" state="interrupted" status="failed" metadata={error_code: "TAX_SERVICE_UNAVAILABLE"}
38
37
 
39
38
  <!-- Failed Chain -->
40
39
  E, [2022-07-17T18:43:15.000000 #3784] ERROR -- BillingWorkflow:
41
- caused_failure={index: 2, class: "CalculateTax", status: "failed"}
42
- threw_failure={index: 1, class: "ValidateCustomer", status: "failed"}
40
+ index=3 chain_id="018c2b95-b764-7615-a924-cc5b910ed1e5" type="Task" class="BillingWorkflow" state="interrupted" status="failed" caused_failure={index: 2, class: "CalculateTax", status: "failed"} threw_failure={index: 1, class: "ValidateCustomer", status: "failed"}
43
41
  ```
44
42
 
45
43
  > [!TIP]
@@ -95,7 +95,8 @@ module CMDx
95
95
  def call(task, **options, &)
96
96
  return yield unless Utils::Condition.evaluate(task, options)
97
97
 
98
- correlation_id =
98
+ correlation_id = task.result.metadata[:correlation_id] ||=
99
+ id ||
99
100
  case callable = options[:id]
100
101
  when Symbol then task.send(callable)
101
102
  when Proc then task.instance_eval(&callable)
@@ -107,9 +108,7 @@ module CMDx
107
108
  end
108
109
  end
109
110
 
110
- result = use(correlation_id, &)
111
- task.result.metadata[:correlation_id] = correlation_id
112
- result
111
+ use(correlation_id, &)
113
112
  end
114
113
 
115
114
  end
data/lib/cmdx/version.rb CHANGED
@@ -2,6 +2,6 @@
2
2
 
3
3
  module CMDx
4
4
 
5
- VERSION = "1.7.1"
5
+ VERSION = "1.7.2"
6
6
 
7
7
  end
@@ -10,7 +10,7 @@ module Cmdx
10
10
 
11
11
  source_root File.expand_path("../../locales", __dir__)
12
12
 
13
- desc "Copies the locale with the given alpha-2 code"
13
+ desc "Copies the locale with the given ISO 639 code"
14
14
 
15
15
  argument :locale, type: :string, default: "en", banner: "locale: en, es, fr, etc"
16
16
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cmdx
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.1
4
+ version: 1.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juan Gomez