cmdx 1.1.2 → 1.5.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/.DS_Store +0 -0
- data/.cursor/prompts/docs.md +4 -1
- data/.cursor/prompts/llms.md +20 -0
- data/.cursor/prompts/rspec.md +4 -1
- data/.cursor/prompts/yardoc.md +3 -2
- data/.cursor/rules/cursor-instructions.mdc +55 -1
- data/.irbrc +6 -0
- data/.rubocop.yml +29 -18
- data/CHANGELOG.md +11 -132
- data/LLM.md +3317 -0
- data/README.md +68 -44
- data/docs/attributes/coercions.md +162 -0
- data/docs/attributes/defaults.md +90 -0
- data/docs/attributes/definitions.md +281 -0
- data/docs/attributes/naming.md +78 -0
- data/docs/attributes/validations.md +309 -0
- data/docs/basics/chain.md +56 -249
- data/docs/basics/context.md +56 -289
- data/docs/basics/execution.md +114 -0
- data/docs/basics/setup.md +37 -334
- data/docs/callbacks.md +89 -467
- data/docs/deprecation.md +91 -174
- data/docs/getting_started.md +212 -202
- data/docs/internationalization.md +11 -647
- data/docs/interruptions/exceptions.md +23 -198
- data/docs/interruptions/faults.md +71 -151
- data/docs/interruptions/halt.md +109 -186
- data/docs/logging.md +44 -256
- data/docs/middlewares.md +113 -426
- data/docs/outcomes/result.md +81 -228
- data/docs/outcomes/states.md +33 -221
- data/docs/outcomes/statuses.md +21 -311
- data/docs/tips_and_tricks.md +120 -70
- data/docs/workflows.md +99 -283
- data/lib/cmdx/.DS_Store +0 -0
- data/lib/cmdx/attribute.rb +229 -0
- data/lib/cmdx/attribute_registry.rb +94 -0
- data/lib/cmdx/attribute_value.rb +193 -0
- data/lib/cmdx/callback_registry.rb +69 -77
- data/lib/cmdx/chain.rb +56 -73
- data/lib/cmdx/coercion_registry.rb +52 -68
- data/lib/cmdx/coercions/array.rb +19 -18
- data/lib/cmdx/coercions/big_decimal.rb +20 -24
- data/lib/cmdx/coercions/boolean.rb +26 -25
- data/lib/cmdx/coercions/complex.rb +21 -22
- data/lib/cmdx/coercions/date.rb +25 -23
- data/lib/cmdx/coercions/date_time.rb +24 -25
- data/lib/cmdx/coercions/float.rb +25 -22
- data/lib/cmdx/coercions/hash.rb +31 -32
- data/lib/cmdx/coercions/integer.rb +30 -24
- data/lib/cmdx/coercions/rational.rb +29 -24
- data/lib/cmdx/coercions/string.rb +19 -22
- data/lib/cmdx/coercions/symbol.rb +37 -0
- data/lib/cmdx/coercions/time.rb +26 -25
- data/lib/cmdx/configuration.rb +49 -108
- data/lib/cmdx/context.rb +222 -44
- data/lib/cmdx/deprecator.rb +61 -0
- data/lib/cmdx/errors.rb +42 -252
- data/lib/cmdx/exceptions.rb +39 -0
- data/lib/cmdx/faults.rb +78 -39
- data/lib/cmdx/freezer.rb +51 -0
- data/lib/cmdx/identifier.rb +30 -0
- data/lib/cmdx/locale.rb +52 -0
- data/lib/cmdx/log_formatters/json.rb +21 -22
- data/lib/cmdx/log_formatters/key_value.rb +20 -22
- data/lib/cmdx/log_formatters/line.rb +15 -22
- data/lib/cmdx/log_formatters/logstash.rb +22 -23
- data/lib/cmdx/log_formatters/raw.rb +16 -22
- data/lib/cmdx/middleware_registry.rb +70 -74
- data/lib/cmdx/middlewares/correlate.rb +90 -54
- data/lib/cmdx/middlewares/runtime.rb +58 -0
- data/lib/cmdx/middlewares/timeout.rb +48 -68
- data/lib/cmdx/railtie.rb +12 -45
- data/lib/cmdx/result.rb +229 -314
- data/lib/cmdx/task.rb +194 -366
- data/lib/cmdx/utils/call.rb +49 -0
- data/lib/cmdx/utils/condition.rb +71 -0
- data/lib/cmdx/utils/format.rb +61 -0
- data/lib/cmdx/validator_registry.rb +63 -72
- data/lib/cmdx/validators/exclusion.rb +38 -67
- data/lib/cmdx/validators/format.rb +48 -49
- data/lib/cmdx/validators/inclusion.rb +43 -74
- data/lib/cmdx/validators/length.rb +101 -162
- data/lib/cmdx/validators/numeric.rb +95 -170
- data/lib/cmdx/validators/presence.rb +37 -50
- data/lib/cmdx/version.rb +1 -1
- data/lib/cmdx/worker.rb +178 -0
- data/lib/cmdx/workflow.rb +85 -81
- data/lib/cmdx.rb +19 -13
- data/lib/generators/cmdx/install_generator.rb +14 -13
- data/lib/generators/cmdx/task_generator.rb +25 -50
- data/lib/generators/cmdx/templates/install.rb +11 -46
- data/lib/generators/cmdx/templates/task.rb.tt +3 -2
- data/lib/locales/en.yml +18 -4
- data/src/cmdx-logo.png +0 -0
- metadata +32 -116
- data/docs/ai_prompts.md +0 -393
- data/docs/basics/call.md +0 -317
- data/docs/configuration.md +0 -344
- data/docs/parameters/coercions.md +0 -396
- data/docs/parameters/defaults.md +0 -335
- data/docs/parameters/definitions.md +0 -446
- data/docs/parameters/namespacing.md +0 -378
- data/docs/parameters/validations.md +0 -405
- data/docs/testing.md +0 -553
- data/lib/cmdx/callback.rb +0 -53
- data/lib/cmdx/chain_inspector.rb +0 -56
- data/lib/cmdx/chain_serializer.rb +0 -63
- data/lib/cmdx/coercion.rb +0 -57
- data/lib/cmdx/coercions/virtual.rb +0 -29
- data/lib/cmdx/core_ext/hash.rb +0 -83
- data/lib/cmdx/core_ext/module.rb +0 -98
- data/lib/cmdx/core_ext/object.rb +0 -125
- data/lib/cmdx/correlator.rb +0 -122
- data/lib/cmdx/error.rb +0 -67
- data/lib/cmdx/fault.rb +0 -140
- data/lib/cmdx/immutator.rb +0 -52
- data/lib/cmdx/lazy_struct.rb +0 -246
- data/lib/cmdx/log_formatters/pretty_json.rb +0 -40
- data/lib/cmdx/log_formatters/pretty_key_value.rb +0 -38
- data/lib/cmdx/log_formatters/pretty_line.rb +0 -41
- data/lib/cmdx/logger.rb +0 -49
- data/lib/cmdx/logger_ansi.rb +0 -68
- data/lib/cmdx/logger_serializer.rb +0 -116
- data/lib/cmdx/middleware.rb +0 -70
- data/lib/cmdx/parameter.rb +0 -312
- data/lib/cmdx/parameter_evaluator.rb +0 -231
- data/lib/cmdx/parameter_inspector.rb +0 -66
- data/lib/cmdx/parameter_registry.rb +0 -106
- data/lib/cmdx/parameter_serializer.rb +0 -59
- data/lib/cmdx/result_ansi.rb +0 -71
- data/lib/cmdx/result_inspector.rb +0 -71
- data/lib/cmdx/result_logger.rb +0 -59
- data/lib/cmdx/result_serializer.rb +0 -104
- data/lib/cmdx/rspec/matchers.rb +0 -28
- data/lib/cmdx/rspec/result_matchers/be_executed.rb +0 -42
- data/lib/cmdx/rspec/result_matchers/be_failed_task.rb +0 -94
- data/lib/cmdx/rspec/result_matchers/be_skipped_task.rb +0 -94
- data/lib/cmdx/rspec/result_matchers/be_state_matchers.rb +0 -59
- data/lib/cmdx/rspec/result_matchers/be_status_matchers.rb +0 -57
- data/lib/cmdx/rspec/result_matchers/be_successful_task.rb +0 -87
- data/lib/cmdx/rspec/result_matchers/have_bad_outcome.rb +0 -51
- data/lib/cmdx/rspec/result_matchers/have_caused_failure.rb +0 -58
- data/lib/cmdx/rspec/result_matchers/have_chain_index.rb +0 -59
- data/lib/cmdx/rspec/result_matchers/have_context.rb +0 -86
- data/lib/cmdx/rspec/result_matchers/have_empty_metadata.rb +0 -54
- data/lib/cmdx/rspec/result_matchers/have_good_outcome.rb +0 -52
- data/lib/cmdx/rspec/result_matchers/have_metadata.rb +0 -114
- data/lib/cmdx/rspec/result_matchers/have_preserved_context.rb +0 -66
- data/lib/cmdx/rspec/result_matchers/have_received_thrown_failure.rb +0 -64
- data/lib/cmdx/rspec/result_matchers/have_runtime.rb +0 -78
- data/lib/cmdx/rspec/result_matchers/have_thrown_failure.rb +0 -76
- data/lib/cmdx/rspec/task_matchers/be_well_formed_task.rb +0 -62
- data/lib/cmdx/rspec/task_matchers/have_callback.rb +0 -85
- data/lib/cmdx/rspec/task_matchers/have_cmd_setting.rb +0 -68
- data/lib/cmdx/rspec/task_matchers/have_executed_callbacks.rb +0 -92
- data/lib/cmdx/rspec/task_matchers/have_middleware.rb +0 -46
- data/lib/cmdx/rspec/task_matchers/have_parameter.rb +0 -181
- data/lib/cmdx/task_deprecator.rb +0 -58
- data/lib/cmdx/task_processor.rb +0 -246
- data/lib/cmdx/task_serializer.rb +0 -57
- data/lib/cmdx/utils/ansi_color.rb +0 -73
- data/lib/cmdx/utils/log_timestamp.rb +0 -36
- data/lib/cmdx/utils/monotonic_runtime.rb +0 -34
- data/lib/cmdx/utils/name_affix.rb +0 -52
- data/lib/cmdx/validator.rb +0 -57
- data/lib/generators/cmdx/templates/workflow.rb.tt +0 -7
- data/lib/generators/cmdx/workflow_generator.rb +0 -84
- data/lib/locales/ar.yml +0 -35
- data/lib/locales/cs.yml +0 -35
- data/lib/locales/da.yml +0 -35
- data/lib/locales/de.yml +0 -35
- data/lib/locales/el.yml +0 -35
- data/lib/locales/es.yml +0 -35
- data/lib/locales/fi.yml +0 -35
- data/lib/locales/fr.yml +0 -35
- data/lib/locales/he.yml +0 -35
- data/lib/locales/hi.yml +0 -35
- data/lib/locales/it.yml +0 -35
- data/lib/locales/ja.yml +0 -35
- data/lib/locales/ko.yml +0 -35
- data/lib/locales/nl.yml +0 -35
- data/lib/locales/no.yml +0 -35
- data/lib/locales/pl.yml +0 -35
- data/lib/locales/pt.yml +0 -35
- data/lib/locales/ru.yml +0 -35
- data/lib/locales/sv.yml +0 -35
- data/lib/locales/th.yml +0 -35
- data/lib/locales/tr.yml +0 -35
- data/lib/locales/vi.yml +0 -35
- data/lib/locales/zh.yml +0 -35
@@ -2,78 +2,114 @@
|
|
2
2
|
|
3
3
|
module CMDx
|
4
4
|
module Middlewares
|
5
|
-
# Middleware
|
6
|
-
#
|
7
|
-
#
|
8
|
-
|
5
|
+
# Middleware for correlating task executions with unique identifiers.
|
6
|
+
#
|
7
|
+
# The Correlate middleware provides thread-safe correlation ID management
|
8
|
+
# for tracking task execution flows across different operations.
|
9
|
+
# It automatically generates correlation IDs when none are provided and
|
10
|
+
# stores them in task result metadata for traceability.
|
11
|
+
module Correlate
|
9
12
|
|
10
|
-
|
11
|
-
attr_reader :id
|
13
|
+
extend self
|
12
14
|
|
13
|
-
|
14
|
-
attr_reader :conditional
|
15
|
+
THREAD_KEY = :cmdx_correlate
|
15
16
|
|
16
|
-
#
|
17
|
+
# Retrieves the current correlation ID from thread-local storage.
|
17
18
|
#
|
18
|
-
# @
|
19
|
-
# @option options [String, Symbol, Proc] :id explicit correlation ID or callable to generate one
|
20
|
-
# @option options [Symbol, Proc] :if condition that must be truthy to apply correlation
|
21
|
-
# @option options [Symbol, Proc] :unless condition that must be falsy to apply correlation
|
19
|
+
# @return [String, nil] The current correlation ID or nil if not set
|
22
20
|
#
|
23
|
-
# @
|
21
|
+
# @example Get current correlation ID
|
22
|
+
# Correlate.id # => "550e8400-e29b-41d4-a716-446655440000"
|
23
|
+
def id
|
24
|
+
Thread.current[THREAD_KEY]
|
25
|
+
end
|
26
|
+
|
27
|
+
# Sets the correlation ID in thread-local storage.
|
24
28
|
#
|
25
|
-
# @
|
26
|
-
#
|
29
|
+
# @param id [String] The correlation ID to set
|
30
|
+
# @return [String] The set correlation ID
|
27
31
|
#
|
28
|
-
# @example
|
29
|
-
#
|
32
|
+
# @example Set correlation ID
|
33
|
+
# Correlate.id = "abc-123-def"
|
34
|
+
def id=(id)
|
35
|
+
Thread.current[THREAD_KEY] = id
|
36
|
+
end
|
37
|
+
|
38
|
+
# Clears the current correlation ID from thread-local storage.
|
30
39
|
#
|
31
|
-
# @
|
32
|
-
# use :middleware, CMDx::Middlewares::Correlate, id: -> { SecureRandom.uuid }
|
40
|
+
# @return [nil] Always returns nil
|
33
41
|
#
|
34
|
-
# @example
|
35
|
-
#
|
36
|
-
def
|
37
|
-
|
38
|
-
@conditional = options.slice(:if, :unless)
|
42
|
+
# @example Clear correlation ID
|
43
|
+
# Correlate.clear
|
44
|
+
def clear
|
45
|
+
Thread.current[THREAD_KEY] = nil
|
39
46
|
end
|
40
47
|
|
41
|
-
#
|
42
|
-
#
|
43
|
-
# the correlation context for tracing purposes.
|
48
|
+
# Temporarily uses a new correlation ID for the duration of a block.
|
49
|
+
# Restores the previous ID after the block completes, even if an error occurs.
|
44
50
|
#
|
45
|
-
# @param
|
46
|
-
# @
|
51
|
+
# @param new_id [String] The correlation ID to use temporarily
|
52
|
+
# @yield The block to execute with the new correlation ID
|
53
|
+
# @return [Object] The result of the yielded block
|
47
54
|
#
|
48
|
-
# @
|
55
|
+
# @example Use temporary correlation ID
|
56
|
+
# Correlate.use("temp-id") do
|
57
|
+
# # Operations here use "temp-id"
|
58
|
+
# perform_operation
|
59
|
+
# end
|
60
|
+
# # Previous ID is restored
|
61
|
+
def use(new_id)
|
62
|
+
old_id = id
|
63
|
+
self.id = new_id
|
64
|
+
yield
|
65
|
+
ensure
|
66
|
+
self.id = old_id
|
67
|
+
end
|
68
|
+
|
69
|
+
# Middleware entry point that applies correlation ID logic to task execution.
|
49
70
|
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
71
|
+
# Evaluates the condition from options and applies correlation ID handling
|
72
|
+
# if enabled. Generates or retrieves correlation IDs based on the :id option
|
73
|
+
# and stores them in task result metadata.
|
53
74
|
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
57
|
-
#
|
75
|
+
# @param task [Task] The task being executed
|
76
|
+
# @param options [Hash] Configuration options for correlation
|
77
|
+
# @option options [Symbol, Proc, Object, nil] :id The correlation ID source
|
78
|
+
# @option options [Symbol, Proc, Object, nil] :if Condition to enable correlation
|
79
|
+
# @option options [Symbol, Proc, Object, nil] :unless Condition to disable correlation
|
58
80
|
#
|
59
|
-
# @
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
|
64
|
-
|
65
|
-
|
81
|
+
# @yield The task execution block
|
82
|
+
#
|
83
|
+
# @return [Object] The result of task execution
|
84
|
+
#
|
85
|
+
# @example Basic usage with automatic ID generation
|
86
|
+
# Correlate.call(task, &block)
|
87
|
+
# @example Use custom correlation ID
|
88
|
+
# Correlate.call(task, id: "custom-123", &block)
|
89
|
+
# @example Use task method for ID
|
90
|
+
# Correlate.call(task, id: :correlation_id, &block)
|
91
|
+
# @example Use proc for dynamic ID generation
|
92
|
+
# Correlate.call(task, id: -> { "dynamic-#{Time.now.to_i}" }, &block)
|
93
|
+
# @example Conditional correlation
|
94
|
+
# Correlate.call(task, if: :enable_correlation, &block)
|
95
|
+
def call(task, **options, &)
|
96
|
+
return yield unless Utils::Condition.evaluate(task, options)
|
66
97
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
98
|
+
correlation_id =
|
99
|
+
case callable = options[:id]
|
100
|
+
when Symbol then task.send(callable)
|
101
|
+
when Proc then task.instance_eval(&callable)
|
102
|
+
else
|
103
|
+
if callable.respond_to?(:call)
|
104
|
+
callable.call(task)
|
105
|
+
else
|
106
|
+
callable || id || Identifier.generate
|
107
|
+
end
|
108
|
+
end
|
72
109
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
end
|
110
|
+
result = use(correlation_id, &)
|
111
|
+
task.result.metadata[:correlation_id] = correlation_id
|
112
|
+
result
|
77
113
|
end
|
78
114
|
|
79
115
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CMDx
|
4
|
+
module Middlewares
|
5
|
+
# Middleware for measuring task execution runtime.
|
6
|
+
#
|
7
|
+
# The Runtime middleware provides performance monitoring by measuring
|
8
|
+
# the execution time of tasks using monotonic clock for accuracy.
|
9
|
+
# It stores runtime measurements in task result metadata for analysis.
|
10
|
+
module Runtime
|
11
|
+
|
12
|
+
extend self
|
13
|
+
|
14
|
+
# Middleware entry point that measures task execution runtime.
|
15
|
+
#
|
16
|
+
# Evaluates the condition from options and measures execution time
|
17
|
+
# if enabled. Uses monotonic clock for precise timing measurements
|
18
|
+
# and stores the result in task metadata.
|
19
|
+
#
|
20
|
+
# @param task [Task] The task being executed
|
21
|
+
# @param options [Hash] Configuration options for runtime measurement
|
22
|
+
# @option options [Symbol, Proc, Object, nil] :if Condition to enable runtime measurement
|
23
|
+
# @option options [Symbol, Proc, Object, nil] :unless Condition to disable runtime measurement
|
24
|
+
#
|
25
|
+
# @yield The task execution block
|
26
|
+
#
|
27
|
+
# @return [Object] The result of task execution
|
28
|
+
#
|
29
|
+
# @example Basic usage with automatic runtime measurement
|
30
|
+
# Runtime.call(task, &block)
|
31
|
+
# @example Conditional runtime measurement
|
32
|
+
# Runtime.call(task, if: :enable_profiling, &block)
|
33
|
+
# @example Disable runtime measurement
|
34
|
+
# Runtime.call(task, unless: :skip_profiling, &block)
|
35
|
+
def call(task, **options)
|
36
|
+
return yield unless Utils::Condition.evaluate(task, options)
|
37
|
+
|
38
|
+
now = monotonic_time
|
39
|
+
result = yield
|
40
|
+
task.result.metadata[:runtime] = monotonic_time - now
|
41
|
+
result
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
# Gets the current monotonic time in milliseconds.
|
47
|
+
#
|
48
|
+
# Uses Process.clock_gettime with CLOCK_MONOTONIC for consistent
|
49
|
+
# timing measurements that are not affected by system clock changes.
|
50
|
+
#
|
51
|
+
# @return [Integer] Current monotonic time in milliseconds
|
52
|
+
def monotonic_time
|
53
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -2,89 +2,69 @@
|
|
2
2
|
|
3
3
|
module CMDx
|
4
4
|
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
5
|
+
# Error raised when task execution exceeds the configured timeout limit.
|
6
|
+
#
|
7
|
+
# This error occurs when a task takes longer to execute than the specified
|
8
|
+
# time limit. Timeout errors are raised by Ruby's Timeout module and are
|
9
|
+
# caught by the middleware to properly fail the task with timeout information.
|
8
10
|
TimeoutError = Class.new(Interrupt)
|
9
11
|
|
10
12
|
module Middlewares
|
11
|
-
# Middleware
|
12
|
-
#
|
13
|
-
#
|
14
|
-
|
13
|
+
# Middleware for enforcing execution time limits on tasks.
|
14
|
+
#
|
15
|
+
# The Timeout middleware provides execution time control by wrapping
|
16
|
+
# task execution with Ruby's Timeout module. It automatically fails
|
17
|
+
# tasks that exceed the configured time limit and provides detailed
|
18
|
+
# error information including the exceeded limit.
|
19
|
+
module Timeout
|
15
20
|
|
16
|
-
|
17
|
-
attr_reader :seconds
|
21
|
+
extend self
|
18
22
|
|
19
|
-
#
|
20
|
-
|
23
|
+
# Default timeout limit in seconds when none is specified.
|
24
|
+
DEFAULT_LIMIT = 3
|
21
25
|
|
22
|
-
#
|
26
|
+
# Middleware entry point that enforces execution time limits.
|
23
27
|
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
# @option options [Symbol, Proc] :unless condition that must be falsy to apply timeout
|
28
|
+
# Evaluates the condition from options and applies timeout control
|
29
|
+
# if enabled. Supports various timeout limit configurations including
|
30
|
+
# numeric values, task method calls, and dynamic proc evaluation.
|
28
31
|
#
|
29
|
-
# @
|
32
|
+
# @param task [Task] The task being executed
|
33
|
+
# @param options [Hash] Configuration options for timeout control
|
34
|
+
# @option options [Numeric, Symbol, Proc, Object] :seconds The timeout limit source
|
35
|
+
# @option options [Symbol, Proc, Object, nil] :if Condition to enable timeout control
|
36
|
+
# @option options [Symbol, Proc, Object, nil] :unless Condition to disable timeout control
|
30
37
|
#
|
31
|
-
# @
|
32
|
-
# use :middleware, CMDx::Middlewares::Timeout.new(seconds: 30)
|
38
|
+
# @yield The task execution block
|
33
39
|
#
|
34
|
-
# @
|
35
|
-
# use :middleware, CMDx::Middlewares::Timeout, seconds: 30
|
40
|
+
# @return [Object] The result of task execution
|
36
41
|
#
|
37
|
-
# @
|
38
|
-
# use :middleware, CMDx::Middlewares::Timeout, seconds: -> { Rails.env.test? ? 1 : 10 }
|
42
|
+
# @raise [TimeoutError] When execution exceeds the configured limit
|
39
43
|
#
|
40
|
-
# @example
|
41
|
-
#
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
50
|
-
|
51
|
-
|
52
|
-
# @param callable [Proc] the callable that executes the task
|
53
|
-
#
|
54
|
-
# @return [Object] the result of the task execution
|
55
|
-
#
|
56
|
-
# @raise [TimeoutError] when task execution exceeds the timeout limit
|
57
|
-
#
|
58
|
-
# @example Task using timeout middleware
|
59
|
-
# class ProcessFileTask < CMDx::Task
|
60
|
-
# use :middleware, CMDx::Middlewares::Timeout, seconds: 10
|
61
|
-
#
|
62
|
-
# def call
|
63
|
-
# # Task execution is automatically wrapped with timeout protection
|
64
|
-
# end
|
65
|
-
# end
|
66
|
-
#
|
67
|
-
# @example Global configuration with conditional timeout
|
68
|
-
# CMDx.configure do |config|
|
69
|
-
# config.middlewares.register CMDx::Middlewares::Timeout, seconds: 30, if: :large_dataset?
|
70
|
-
# end
|
71
|
-
def call(task, callable)
|
72
|
-
# Check if timeout should be applied based on conditions
|
73
|
-
return callable.call(task) unless task.cmdx_eval(conditional)
|
74
|
-
|
75
|
-
# Get seconds using yield for dynamic generation
|
76
|
-
limit = task.cmdx_yield(seconds) || 3
|
44
|
+
# @example Basic usage with default 3 second timeout
|
45
|
+
# Timeout.call(task, &block)
|
46
|
+
# @example Custom timeout limit in seconds
|
47
|
+
# Timeout.call(task, seconds: 10, &block)
|
48
|
+
# @example Use task method for timeout limit
|
49
|
+
# Timeout.call(task, seconds: :timeout_limit, &block)
|
50
|
+
# @example Use proc for dynamic timeout calculation
|
51
|
+
# Timeout.call(task, seconds: -> { calculate_timeout }, &block)
|
52
|
+
# @example Conditional timeout control
|
53
|
+
# Timeout.call(task, if: :enable_timeout, &block)
|
54
|
+
def call(task, **options, &)
|
55
|
+
return yield unless Utils::Condition.evaluate(task, options)
|
77
56
|
|
78
|
-
|
79
|
-
|
57
|
+
limit =
|
58
|
+
case callable = options[:seconds]
|
59
|
+
when Numeric then callable
|
60
|
+
when Symbol then task.send(callable)
|
61
|
+
when Proc then task.instance_eval(&callable)
|
62
|
+
else callable.respond_to?(:call) ? callable.call(task) : DEFAULT_LIMIT
|
63
|
+
end
|
80
64
|
|
81
|
-
#
|
82
|
-
::Timeout.timeout(limit, TimeoutError, "execution exceeded #{limit} seconds") do
|
83
|
-
callable.call(task)
|
84
|
-
end
|
65
|
+
::Timeout.timeout(limit, TimeoutError, "execution exceeded #{limit} seconds", &)
|
85
66
|
rescue TimeoutError => e
|
86
|
-
task.fail!(
|
87
|
-
task.result
|
67
|
+
task.result.tap { |r| r.fail!("[#{e.class}] #{e.message}", cause: e, limit:) }
|
88
68
|
end
|
89
69
|
|
90
70
|
end
|
data/lib/cmdx/railtie.rb
CHANGED
@@ -1,32 +1,29 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module CMDx
|
4
|
-
# Rails integration
|
5
|
-
#
|
6
|
-
# Provides Rails-specific configuration including internationalization
|
7
|
-
# locale loading and autoload path configuration for CMDx workflows and tasks.
|
4
|
+
# Rails integration class that automatically configures CMDx when the Rails
|
5
|
+
# application initializes. Handles locale configuration and I18n setup.
|
8
6
|
class Railtie < Rails::Railtie
|
9
7
|
|
10
8
|
railtie_name :cmdx
|
11
9
|
|
12
|
-
#
|
10
|
+
# Configures CMDx locales during Rails application initialization.
|
13
11
|
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
12
|
+
# Iterates through available locales from the Rails configuration and loads
|
13
|
+
# corresponding CMDx locale files. Reloads the I18n system to ensure
|
14
|
+
# all locales are properly registered.
|
17
15
|
#
|
18
16
|
# @param app [Rails::Application] the Rails application instance
|
19
17
|
#
|
20
|
-
# @
|
18
|
+
# @raise [LoadError] if locale files cannot be loaded
|
21
19
|
#
|
22
|
-
# @
|
23
|
-
#
|
24
|
-
#
|
25
|
-
# #
|
26
|
-
# # when CMDx is included in a Rails application
|
20
|
+
# @example
|
21
|
+
# # This initializer runs automatically when Rails starts
|
22
|
+
# # It will load locales like en.yml, es.yml, fr.yml if they exist
|
23
|
+
# # in the CMDx gem's locales directory
|
27
24
|
initializer("cmdx.configure_locales") do |app|
|
28
25
|
Array(app.config.i18n.available_locales).each do |locale|
|
29
|
-
path =
|
26
|
+
path = CMDx.gem_path.join("lib/locales/#{locale}.yml")
|
30
27
|
next unless File.file?(path)
|
31
28
|
|
32
29
|
I18n.load_path << path
|
@@ -35,35 +32,5 @@ module CMDx
|
|
35
32
|
I18n.reload!
|
36
33
|
end
|
37
34
|
|
38
|
-
# Configure Rails autoload paths for CMDx components.
|
39
|
-
#
|
40
|
-
# Adds the app/cmds directory to Rails autoload paths and configures
|
41
|
-
# autoloaders to collapse the workflows and tasks subdirectories.
|
42
|
-
# This enables Rails to automatically load CMDx workflows and tasks
|
43
|
-
# from the conventional directory structure.
|
44
|
-
#
|
45
|
-
# @param app [Rails::Application] the Rails application instance
|
46
|
-
#
|
47
|
-
# @return [void]
|
48
|
-
#
|
49
|
-
# @raise [StandardError] if autoloader configuration fails
|
50
|
-
#
|
51
|
-
# @example Configure autoload paths during Rails initialization
|
52
|
-
# # This initializer runs automatically during Rails boot
|
53
|
-
# # Enables loading of:
|
54
|
-
# # - app/cmds/workflows/my_workflow.rb
|
55
|
-
# # - app/cmds/tasks/my_task.rb
|
56
|
-
initializer("cmdx.configure_rails_auto_load_paths") do |app|
|
57
|
-
app.config.autoload_paths += %w[app/cmds]
|
58
|
-
|
59
|
-
types = %w[workflows tasks]
|
60
|
-
app.autoloaders.each do |autoloader|
|
61
|
-
types.each do |concept|
|
62
|
-
dir = app.root.join("app/cmds/#{concept}")
|
63
|
-
autoloader.collapse(dir)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
35
|
end
|
69
36
|
end
|