fractor 0.1.8 → 0.1.10

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: e02a928040e2df09a69eda8ffa10367d5e698868a44643912a747a99b27111fa
4
- data.tar.gz: e02247543fd89c0856ac6ce8e18c538ef32c5e1f82bce856b666b7db51b49d26
3
+ metadata.gz: 22b2448a14f44c78c6b4970d9529aa9e88257ff63423be18e57dd87290f5247b
4
+ data.tar.gz: 27a514ab149f2115e5e53fe0c4a3199d09adeb355789ce21ff85ab93b8cb1891
5
5
  SHA512:
6
- metadata.gz: 8b664bc5b52225acc157a3f37a1ae97a6a621c08398d2de6b7759a03aceb1bb356d7242da173d6f16f331e0433ab29b60b067250b57422ab5d3c9bed2a284cc5
7
- data.tar.gz: 26fa65f4a034857688d3fd45f0702eed50a9c07262107e4a43b1da0d77656988137a5242c661e03ef571aa35cfb1ed11a9e48b7fa17f626e74eb5ab71111a3d8
6
+ metadata.gz: 2da27fec2e527d266dc85e3fc29fd646740e76c8b9e77a5c6171bd79fa6054f4a0bae79fc72d99aa4ca683a5fcf5a9f079aeef35123ce4e25de846948ba9a991
7
+ data.tar.gz: 7d01bbb10b527954f8afdb1dd9e9e8858342a71fddf3734bbc178a4ab0c227e9b69ee4f336b3f37016a17da4ea1e69c1dc65a48fa31de73cef6469bf413e851e
data/.rubocop_todo.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2026-01-22 06:39:26 UTC using RuboCop version 1.82.1.
3
+ # on 2026-01-27 14:55:44 UTC using RuboCop version 1.82.1.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
@@ -11,47 +11,19 @@ Gemspec/RequiredRubyVersion:
11
11
  Exclude:
12
12
  - 'fractor.gemspec'
13
13
 
14
- # Offense count: 4
15
- # This cop supports safe autocorrection (--autocorrect).
16
- # Configuration parameters: EnforcedStyle, IndentationWidth.
17
- # SupportedStyles: with_first_argument, with_fixed_indentation
18
- Layout/ArgumentAlignment:
19
- Exclude:
20
- - 'spec/fractor/main_loop_handler3_spec.rb'
21
- - 'spec/fractor/main_loop_handler4_spec.rb'
22
- - 'spec/fractor/supervisor_shutdown_spec.rb'
23
-
24
- # Offense count: 2
25
- # This cop supports safe autocorrection (--autocorrect).
26
- # Configuration parameters: EnforcedStyleAlignWith.
27
- # SupportedStylesAlignWith: either, start_of_block, start_of_line
28
- Layout/BlockAlignment:
29
- Exclude:
30
- - 'spec/fractor/main_loop_handler3_spec.rb'
31
- - 'spec/fractor/main_loop_handler4_spec.rb'
32
-
33
- # Offense count: 455
14
+ # Offense count: 498
34
15
  # This cop supports safe autocorrection (--autocorrect).
35
16
  # Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
36
17
  # URISchemes: http, https
37
18
  Layout/LineLength:
38
19
  Enabled: false
39
20
 
40
- # Offense count: 4
41
- # This cop supports safe autocorrection (--autocorrect).
42
- # Configuration parameters: AllowInHeredoc.
43
- Layout/TrailingWhitespace:
44
- Exclude:
45
- - 'spec/fractor/main_loop_handler3_spec.rb'
46
- - 'spec/fractor/main_loop_handler4_spec.rb'
47
- - 'spec/fractor/supervisor_shutdown_spec.rb'
48
-
49
21
  # Offense count: 1
50
22
  Lint/BinaryOperatorWithIdenticalOperands:
51
23
  Exclude:
52
24
  - 'spec/fractor/priority_work_spec.rb'
53
25
 
54
- # Offense count: 14
26
+ # Offense count: 20
55
27
  # Configuration parameters: AllowedMethods.
56
28
  # AllowedMethods: enums
57
29
  Lint/ConstantDefinitionInBlock:
@@ -60,7 +32,10 @@ Lint/ConstantDefinitionInBlock:
60
32
  - 'spec/examples/performance_monitoring_spec.rb'
61
33
  - 'spec/examples/priority_work_example_spec.rb'
62
34
  - 'spec/fractor/integration_spec.rb'
35
+ - 'spec/fractor/persistent_work_queue_spec.rb'
36
+ - 'spec/fractor/result_cache_spec.rb'
63
37
  - 'spec/fractor/work_spec.rb'
38
+ - 'spec/fractor/work_timeout_spec.rb'
64
39
  - 'spec/fractor/worker_timeout_spec.rb'
65
40
  - 'spec/fractor/workflow/execution_strategy_spec.rb'
66
41
 
@@ -77,10 +52,11 @@ Lint/HashCompareByIdentity:
77
52
  - 'lib/fractor/work_distribution_manager.rb'
78
53
  - 'spec/fractor/work_distribution_manager_spec.rb'
79
54
 
80
- # Offense count: 1
55
+ # Offense count: 4
81
56
  # Configuration parameters: AllowedParentClasses.
82
57
  Lint/MissingSuper:
83
58
  Exclude:
59
+ - 'lib/fractor/queue_persister.rb'
84
60
  - 'spec/fractor/wrapped_ractor3_spec.rb'
85
61
 
86
62
  # Offense count: 5
@@ -91,7 +67,7 @@ Lint/RescueException:
91
67
  - 'lib/fractor/wrapped_ractor3.rb'
92
68
  - 'lib/fractor/wrapped_ractor4.rb'
93
69
 
94
- # Offense count: 4
70
+ # Offense count: 2
95
71
  # This cop supports safe autocorrection (--autocorrect).
96
72
  # Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods, NotImplementedExceptions.
97
73
  # NotImplementedExceptions: NotImplementedError
@@ -99,9 +75,14 @@ Lint/UnusedMethodArgument:
99
75
  Exclude:
100
76
  - 'lib/fractor/workflow.rb'
101
77
  - 'lib/fractor/wrapped_ractor3.rb'
102
- - 'spec/fractor/wrapped_ractor3_spec.rb'
103
78
 
104
- # Offense count: 88
79
+ # Offense count: 1
80
+ # This cop supports safe autocorrection (--autocorrect).
81
+ Lint/UselessAssignment:
82
+ Exclude:
83
+ - 'lib/fractor/wrapped_ractor.rb'
84
+
85
+ # Offense count: 92
105
86
  # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
106
87
  Metrics/AbcSize:
107
88
  Enabled: false
@@ -110,24 +91,24 @@ Metrics/AbcSize:
110
91
  # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode.
111
92
  # AllowedMethods: refine
112
93
  Metrics/BlockLength:
113
- Max: 105
94
+ Max: 110
114
95
 
115
- # Offense count: 61
96
+ # Offense count: 64
116
97
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
117
98
  Metrics/CyclomaticComplexity:
118
99
  Enabled: false
119
100
 
120
- # Offense count: 142
101
+ # Offense count: 155
121
102
  # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
122
103
  Metrics/MethodLength:
123
- Max: 117
104
+ Max: 122
124
105
 
125
- # Offense count: 9
106
+ # Offense count: 10
126
107
  # Configuration parameters: CountKeywordArgs, MaxOptionalParameters.
127
108
  Metrics/ParameterLists:
128
109
  Max: 9
129
110
 
130
- # Offense count: 46
111
+ # Offense count: 50
131
112
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
132
113
  Metrics/PerceivedComplexity:
133
114
  Enabled: false
@@ -151,17 +132,14 @@ Naming/PredicatePrefix:
151
132
  - '../../../.cache/rubocop_cache/spec/**/*'
152
133
  - 'spec/support/workflow_helpers.rb'
153
134
 
154
- # Offense count: 9
135
+ # Offense count: 6
155
136
  # Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers, AllowedPatterns.
156
137
  # SupportedStyles: snake_case, normalcase, non_integer
157
138
  # AllowedIdentifiers: TLS1_1, TLS1_2, capture3, iso8601, rfc1123_date, rfc822, rfc2822, rfc3339, x86_64
158
139
  Naming/VariableNumber:
159
140
  Exclude:
160
141
  - 'lib/fractor/error_statistics.rb'
161
- - 'lib/fractor/main_loop_handler.rb'
162
142
  - 'lib/fractor/main_loop_handler4.rb'
163
- - 'lib/fractor/supervisor.rb'
164
- - 'lib/fractor/wrapped_ractor.rb'
165
143
  - 'spec/examples/error_reporting_spec.rb'
166
144
  - 'spec/fractor/workflow/retry_orchestrator_spec.rb'
167
145
 
@@ -185,21 +163,12 @@ RSpec/ContextWording:
185
163
  - 'spec/fractor/supervisor_spec.rb'
186
164
  - 'spec/fractor_spec.rb'
187
165
 
188
- # Offense count: 27
166
+ # Offense count: 29
189
167
  # Configuration parameters: IgnoredMetadata.
190
168
  RSpec/DescribeClass:
191
169
  Enabled: false
192
170
 
193
- # Offense count: 3
194
- # This cop supports unsafe autocorrection (--autocorrect-all).
195
- # Configuration parameters: SkipBlocks, EnforcedStyle, OnlyStaticConstants.
196
- # SupportedStyles: described_class, explicit
197
- RSpec/DescribedClass:
198
- Exclude:
199
- - 'spec/fractor/worker_spec.rb'
200
- - 'spec/fractor/worker_timeout_spec.rb'
201
-
202
- # Offense count: 510
171
+ # Offense count: 549
203
172
  # Configuration parameters: CountAsOne.
204
173
  RSpec/ExampleLength:
205
174
  Max: 47
@@ -246,18 +215,21 @@ RSpec/InstanceVariable:
246
215
  - 'spec/examples/workflow/dead_letter_queue_workflow_spec.rb'
247
216
  - 'spec/fractor/integration_spec.rb'
248
217
 
249
- # Offense count: 16
218
+ # Offense count: 22
250
219
  RSpec/LeakyConstantDeclaration:
251
220
  Exclude:
252
221
  - 'spec/examples/error_reporting_spec.rb'
253
222
  - 'spec/examples/performance_monitoring_spec.rb'
254
223
  - 'spec/examples/priority_work_example_spec.rb'
255
224
  - 'spec/fractor/integration_spec.rb'
225
+ - 'spec/fractor/persistent_work_queue_spec.rb'
226
+ - 'spec/fractor/result_cache_spec.rb'
256
227
  - 'spec/fractor/work_spec.rb'
228
+ - 'spec/fractor/work_timeout_spec.rb'
257
229
  - 'spec/fractor/worker_timeout_spec.rb'
258
230
  - 'spec/fractor/workflow/execution_strategy_spec.rb'
259
231
 
260
- # Offense count: 19
232
+ # Offense count: 24
261
233
  # Configuration parameters: EnforcedStyle.
262
234
  # SupportedStyles: have_received, receive
263
235
  RSpec/MessageSpies:
@@ -265,21 +237,23 @@ RSpec/MessageSpies:
265
237
  - 'spec/fractor/main_loop_handler_spec.rb'
266
238
  - 'spec/fractor/shutdown_handler_spec.rb'
267
239
 
268
- # Offense count: 6
240
+ # Offense count: 8
269
241
  RSpec/MultipleDescribes:
270
242
  Exclude:
271
243
  - 'spec/examples/workflow/simplified_workflow_spec.rb'
244
+ - 'spec/fractor/persistent_work_queue_spec.rb'
245
+ - 'spec/fractor/work_timeout_spec.rb'
272
246
  - 'spec/fractor/worker_timeout_spec.rb'
273
247
  - 'spec/fractor/workflow/dead_letter_queue_spec.rb'
274
248
  - 'spec/fractor/workflow/execution_strategy_spec.rb'
275
249
  - 'spec/fractor/workflow/retry_config_spec.rb'
276
250
  - 'spec/fractor/workflow/retry_strategy_spec.rb'
277
251
 
278
- # Offense count: 605
252
+ # Offense count: 636
279
253
  RSpec/MultipleExpectations:
280
254
  Max: 12
281
255
 
282
- # Offense count: 50
256
+ # Offense count: 52
283
257
  # Configuration parameters: AllowSubject.
284
258
  RSpec/MultipleMemoizedHelpers:
285
259
  Max: 9
@@ -321,9 +295,30 @@ Security/Eval:
321
295
  Exclude:
322
296
  - 'lib/fractor/cli.rb'
323
297
 
298
+ # Offense count: 1
299
+ Security/MarshalLoad:
300
+ Exclude:
301
+ - 'lib/fractor/queue_persister.rb'
302
+
324
303
  # Offense count: 1
325
304
  # Configuration parameters: AllowedMethods.
326
305
  # AllowedMethods: respond_to_missing?
327
306
  Style/OptionalBooleanParameter:
328
307
  Exclude:
329
308
  - 'lib/fractor/workflow/job.rb'
309
+
310
+ # Offense count: 1
311
+ # This cop supports safe autocorrection (--autocorrect).
312
+ # Configuration parameters: AllowedMethods.
313
+ # AllowedMethods: nonzero?
314
+ Style/RedundantCondition:
315
+ Exclude:
316
+ - 'lib/fractor/supervisor.rb'
317
+
318
+ # Offense count: 1
319
+ # This cop supports safe autocorrection (--autocorrect).
320
+ # Configuration parameters: EnforcedStyleForMultiline.
321
+ # SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma
322
+ Style/TrailingCommaInArguments:
323
+ Exclude:
324
+ - 'lib/fractor/supervisor.rb'
data/README.adoc CHANGED
@@ -82,6 +82,143 @@ puts "Results: #{supervisor.results.results.map(&:result)}"
82
82
  # => Results: [2, 4, 6]
83
83
  ----
84
84
 
85
+ === Timeout Configuration
86
+
87
+ Fractor supports flexible timeout configuration at three levels:
88
+
89
+ [cols="1,2,4"]
90
+ |===
91
+ |Level |Syntax |Description
92
+
93
+ |Global
94
+ |`Fractor.configure`
95
+ |Sets default timeout for all workers
96
+
97
+ |Worker
98
+ |`Worker.timeout` class method
99
+ |Sets timeout for all work processed by a worker
100
+
101
+ |Work item
102
+ |`Work.new(input, timeout: N)`
103
+ |Overrides worker timeout for specific work item
104
+ |===
105
+
106
+ [source,ruby]
107
+ ----
108
+ # 1. Global default (optional)
109
+ Fractor.configure do |config|
110
+ config.default_worker_timeout = 60 # 60 seconds
111
+ end
112
+
113
+ # 2. Worker-level timeout
114
+ class FastWorker < Fractor::Worker
115
+ timeout 10 # 10 second timeout for this worker
116
+
117
+ def process(work)
118
+ Fractor::WorkResult.new(result: work.input * 2, work: work)
119
+ end
120
+ end
121
+
122
+ # 3. Per-work-item timeout (overrides worker timeout)
123
+ class MyWork < Fractor::Work
124
+ def initialize(value, timeout: nil)
125
+ super({ value: value }, timeout: timeout)
126
+ end
127
+ end
128
+
129
+ supervisor = Fractor::Supervisor.new(
130
+ worker_pools: [{ worker_class: FastWorker }]
131
+ )
132
+
133
+ # Mix work items with different timeouts
134
+ fast_work = MyWork.new(1, timeout: 5) # 5 seconds
135
+ normal_work = MyWork.new(2) # uses worker's 10s timeout
136
+ slow_work = MyWork.new(3, timeout: 30) # 30 seconds
137
+
138
+ supervisor.add_work_items([fast_work, normal_work, slow_work])
139
+ supervisor.run
140
+ ----
141
+
142
+ When a timeout occurs, the work item is marked as failed with `error_category: :timeout` and can be retried if using the workflow system.
143
+
144
+ === Queue Persistence
145
+
146
+ For critical applications, work queues can be persisted to disk for crash recovery:
147
+
148
+ [source,ruby]
149
+ ----
150
+ # Create a persistent queue with automatic saving
151
+ queue = Fractor::PersistentWorkQueue.new("data/queue.json")
152
+
153
+ # Add work items - automatically saved
154
+ queue << MyWork.new(data1)
155
+ queue << MyWork.new(data2)
156
+
157
+ # Use with ContinuousServer for crash recovery
158
+ server = Fractor::ContinuousServer.new(
159
+ worker_pools: [{ worker_class: MyWorker }],
160
+ work_queue: queue
161
+ )
162
+
163
+ # Load any previous work items on startup
164
+ queue.load
165
+
166
+ server.run
167
+ ----
168
+
169
+ Supported persistence formats:
170
+ * **JSON** (default) - Human-readable, widely compatible
171
+ * **YAML** - More readable than JSON
172
+ * **Marshal** - Binary format, faster but Ruby-specific
173
+
174
+ === Result Caching
175
+
176
+ For expensive, deterministic operations, Fractor provides a result cache to avoid redundant processing of identical work items:
177
+
178
+ [source,ruby]
179
+ ----
180
+ # Create a cache with TTL (time-to-live)
181
+ cache = Fractor::ResultCache.new(ttl: 300) # 5 minutes
182
+
183
+ # Or with size limit
184
+ cache = Fractor::ResultCache.new(max_size: 1000)
185
+
186
+ # Or with memory limit
187
+ cache = Fractor::ResultCache.new(max_memory: 1024 * 1024) # 1MB
188
+
189
+ # Use the cache
190
+ result = cache.get(work) do
191
+ # This block only runs if work is not cached
192
+ expensive_operation(work)
193
+ end
194
+
195
+ # Check if work is cached
196
+ if cache.has?(work)
197
+ puts "Result is cached!"
198
+ end
199
+
200
+ # Manual cache operations
201
+ cache.set(work, result) # Store a result
202
+ cache.invalidate(work) # Remove a cached result
203
+ cache.clear # Remove all cached results
204
+
205
+ # Get cache statistics
206
+ stats = cache.stats
207
+ puts "Cache hit rate: #{stats[:hit_rate]}%"
208
+ ----
209
+
210
+ The cache generates consistent keys based on:
211
+ * Work class name
212
+ * Work input data
213
+ * Work timeout (if set)
214
+
215
+ This means identical work items with the same input and timeout will share cached results.
216
+
217
+ Cache eviction policies:
218
+ * **TTL** - Entries expire after a configured time
219
+ * **LRU** - Least-recently-used entries are evicted when max_size is reached
220
+ * **Memory-based** - Entries are evicted when max_memory is reached
221
+
85
222
  == Key features
86
223
 
87
224
  * *Function-driven*: Define processing logic by subclassing `Fractor::Worker`