fractor 0.1.6 → 0.1.7
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/.rubocop_todo.yml +227 -102
- data/README.adoc +113 -1940
- data/docs/.lycheeignore +16 -0
- data/docs/Gemfile +24 -0
- data/docs/README.md +157 -0
- data/docs/_config.yml +151 -0
- data/docs/_features/error-handling.adoc +1192 -0
- data/docs/_features/index.adoc +80 -0
- data/docs/_features/monitoring.adoc +589 -0
- data/docs/_features/signal-handling.adoc +202 -0
- data/docs/_features/workflows.adoc +1235 -0
- data/docs/_guides/continuous-mode.adoc +736 -0
- data/docs/_guides/cookbook.adoc +1133 -0
- data/docs/_guides/index.adoc +55 -0
- data/docs/_guides/pipeline-mode.adoc +730 -0
- data/docs/_guides/troubleshooting.adoc +358 -0
- data/docs/_pages/architecture.adoc +1390 -0
- data/docs/_pages/core-concepts.adoc +1392 -0
- data/docs/_pages/design-principles.adoc +862 -0
- data/docs/_pages/getting-started.adoc +290 -0
- data/docs/_pages/installation.adoc +143 -0
- data/docs/_reference/api.adoc +1080 -0
- data/docs/_reference/error-reporting.adoc +670 -0
- data/docs/_reference/examples.adoc +181 -0
- data/docs/_reference/index.adoc +96 -0
- data/docs/_reference/troubleshooting.adoc +862 -0
- data/docs/_tutorials/complex-workflows.adoc +1022 -0
- data/docs/_tutorials/data-processing-pipeline.adoc +740 -0
- data/docs/_tutorials/first-application.adoc +384 -0
- data/docs/_tutorials/index.adoc +48 -0
- data/docs/_tutorials/long-running-services.adoc +931 -0
- data/docs/assets/images/favicon-16.png +0 -0
- data/docs/assets/images/favicon-32.png +0 -0
- data/docs/assets/images/favicon-48.png +0 -0
- data/docs/assets/images/favicon.ico +0 -0
- data/docs/assets/images/favicon.png +0 -0
- data/docs/assets/images/favicon.svg +45 -0
- data/docs/assets/images/fractor-icon.svg +49 -0
- data/docs/assets/images/fractor-logo.svg +61 -0
- data/docs/index.adoc +131 -0
- data/docs/lychee.toml +39 -0
- data/examples/api_aggregator/README.adoc +627 -0
- data/examples/api_aggregator/api_aggregator.rb +376 -0
- data/examples/auto_detection/README.adoc +407 -29
- data/examples/continuous_chat_common/message_protocol.rb +1 -1
- data/examples/error_reporting.rb +207 -0
- data/examples/file_processor/README.adoc +170 -0
- data/examples/file_processor/file_processor.rb +615 -0
- data/examples/file_processor/sample_files/invalid.csv +1 -0
- data/examples/file_processor/sample_files/orders.xml +24 -0
- data/examples/file_processor/sample_files/products.json +23 -0
- data/examples/file_processor/sample_files/users.csv +6 -0
- data/examples/hierarchical_hasher/README.adoc +629 -41
- data/examples/image_processor/README.adoc +610 -0
- data/examples/image_processor/image_processor.rb +349 -0
- data/examples/image_processor/processed_images/sample_10_processed.jpg.json +12 -0
- data/examples/image_processor/processed_images/sample_1_processed.jpg.json +12 -0
- data/examples/image_processor/processed_images/sample_2_processed.jpg.json +12 -0
- data/examples/image_processor/processed_images/sample_3_processed.jpg.json +12 -0
- data/examples/image_processor/processed_images/sample_4_processed.jpg.json +12 -0
- data/examples/image_processor/processed_images/sample_5_processed.jpg.json +12 -0
- data/examples/image_processor/processed_images/sample_6_processed.jpg.json +12 -0
- data/examples/image_processor/processed_images/sample_7_processed.jpg.json +12 -0
- data/examples/image_processor/processed_images/sample_8_processed.jpg.json +12 -0
- data/examples/image_processor/processed_images/sample_9_processed.jpg.json +12 -0
- data/examples/image_processor/test_images/sample_1.png +1 -0
- data/examples/image_processor/test_images/sample_10.png +1 -0
- data/examples/image_processor/test_images/sample_2.png +1 -0
- data/examples/image_processor/test_images/sample_3.png +1 -0
- data/examples/image_processor/test_images/sample_4.png +1 -0
- data/examples/image_processor/test_images/sample_5.png +1 -0
- data/examples/image_processor/test_images/sample_6.png +1 -0
- data/examples/image_processor/test_images/sample_7.png +1 -0
- data/examples/image_processor/test_images/sample_8.png +1 -0
- data/examples/image_processor/test_images/sample_9.png +1 -0
- data/examples/log_analyzer/README.adoc +662 -0
- data/examples/log_analyzer/log_analyzer.rb +579 -0
- data/examples/log_analyzer/sample_logs/apache.log +20 -0
- data/examples/log_analyzer/sample_logs/json.log +15 -0
- data/examples/log_analyzer/sample_logs/nginx.log +15 -0
- data/examples/log_analyzer/sample_logs/rails.log +29 -0
- data/examples/multi_work_type/README.adoc +576 -26
- data/examples/performance_monitoring.rb +120 -0
- data/examples/pipeline_processing/README.adoc +740 -26
- data/examples/pipeline_processing/pipeline_processing.rb +2 -2
- data/examples/priority_work_example.rb +155 -0
- data/examples/producer_subscriber/README.adoc +889 -46
- data/examples/scatter_gather/README.adoc +829 -27
- data/examples/simple/README.adoc +347 -0
- data/examples/specialized_workers/README.adoc +622 -26
- data/examples/specialized_workers/specialized_workers.rb +44 -8
- data/examples/stream_processor/README.adoc +206 -0
- data/examples/stream_processor/stream_processor.rb +284 -0
- data/examples/web_scraper/README.adoc +625 -0
- data/examples/web_scraper/web_scraper.rb +285 -0
- data/examples/workflow/README.adoc +406 -0
- data/examples/workflow/circuit_breaker/README.adoc +360 -0
- data/examples/workflow/circuit_breaker/circuit_breaker_workflow.rb +225 -0
- data/examples/workflow/conditional/README.adoc +483 -0
- data/examples/workflow/conditional/conditional_workflow.rb +215 -0
- data/examples/workflow/dead_letter_queue/README.adoc +374 -0
- data/examples/workflow/dead_letter_queue/dead_letter_queue_workflow.rb +217 -0
- data/examples/workflow/fan_out/README.adoc +381 -0
- data/examples/workflow/fan_out/fan_out_workflow.rb +202 -0
- data/examples/workflow/retry/README.adoc +248 -0
- data/examples/workflow/retry/retry_workflow.rb +195 -0
- data/examples/workflow/simple_linear/README.adoc +267 -0
- data/examples/workflow/simple_linear/simple_linear_workflow.rb +175 -0
- data/examples/workflow/simplified/README.adoc +329 -0
- data/examples/workflow/simplified/simplified_workflow.rb +222 -0
- data/exe/fractor +10 -0
- data/lib/fractor/cli.rb +288 -0
- data/lib/fractor/configuration.rb +307 -0
- data/lib/fractor/continuous_server.rb +60 -65
- data/lib/fractor/error_formatter.rb +72 -0
- data/lib/fractor/error_report_generator.rb +152 -0
- data/lib/fractor/error_reporter.rb +244 -0
- data/lib/fractor/error_statistics.rb +147 -0
- data/lib/fractor/execution_tracer.rb +162 -0
- data/lib/fractor/logger.rb +230 -0
- data/lib/fractor/main_loop_handler.rb +406 -0
- data/lib/fractor/main_loop_handler3.rb +135 -0
- data/lib/fractor/main_loop_handler4.rb +299 -0
- data/lib/fractor/performance_metrics_collector.rb +181 -0
- data/lib/fractor/performance_monitor.rb +215 -0
- data/lib/fractor/performance_report_generator.rb +202 -0
- data/lib/fractor/priority_work.rb +93 -0
- data/lib/fractor/priority_work_queue.rb +189 -0
- data/lib/fractor/result_aggregator.rb +32 -0
- data/lib/fractor/shutdown_handler.rb +168 -0
- data/lib/fractor/signal_handler.rb +80 -0
- data/lib/fractor/supervisor.rb +382 -269
- data/lib/fractor/supervisor_logger.rb +88 -0
- data/lib/fractor/version.rb +1 -1
- data/lib/fractor/work.rb +12 -0
- data/lib/fractor/work_distribution_manager.rb +151 -0
- data/lib/fractor/work_queue.rb +20 -0
- data/lib/fractor/work_result.rb +181 -9
- data/lib/fractor/worker.rb +73 -0
- data/lib/fractor/workflow/builder.rb +210 -0
- data/lib/fractor/workflow/chain_builder.rb +169 -0
- data/lib/fractor/workflow/circuit_breaker.rb +183 -0
- data/lib/fractor/workflow/circuit_breaker_orchestrator.rb +208 -0
- data/lib/fractor/workflow/circuit_breaker_registry.rb +112 -0
- data/lib/fractor/workflow/dead_letter_queue.rb +334 -0
- data/lib/fractor/workflow/execution_hooks.rb +39 -0
- data/lib/fractor/workflow/execution_strategy.rb +225 -0
- data/lib/fractor/workflow/execution_trace.rb +134 -0
- data/lib/fractor/workflow/helpers.rb +191 -0
- data/lib/fractor/workflow/job.rb +290 -0
- data/lib/fractor/workflow/job_dependency_validator.rb +120 -0
- data/lib/fractor/workflow/logger.rb +110 -0
- data/lib/fractor/workflow/pre_execution_context.rb +193 -0
- data/lib/fractor/workflow/retry_config.rb +156 -0
- data/lib/fractor/workflow/retry_orchestrator.rb +184 -0
- data/lib/fractor/workflow/retry_strategy.rb +93 -0
- data/lib/fractor/workflow/structured_logger.rb +30 -0
- data/lib/fractor/workflow/type_compatibility_validator.rb +222 -0
- data/lib/fractor/workflow/visualizer.rb +211 -0
- data/lib/fractor/workflow/workflow_context.rb +132 -0
- data/lib/fractor/workflow/workflow_executor.rb +669 -0
- data/lib/fractor/workflow/workflow_result.rb +55 -0
- data/lib/fractor/workflow/workflow_validator.rb +295 -0
- data/lib/fractor/workflow.rb +333 -0
- data/lib/fractor/wrapped_ractor.rb +66 -101
- data/lib/fractor/wrapped_ractor3.rb +161 -0
- data/lib/fractor/wrapped_ractor4.rb +242 -0
- data/lib/fractor.rb +92 -4
- metadata +179 -6
- data/tests/sample.rb.bak +0 -309
- data/tests/sample_working.rb.bak +0 -209
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: default
|
|
3
|
+
title: Troubleshooting Guide
|
|
4
|
+
nav_order: 5
|
|
5
|
+
---
|
|
6
|
+
== Troubleshooting Guide
|
|
7
|
+
|
|
8
|
+
This guide helps you diagnose and resolve common issues when using Fractor.
|
|
9
|
+
|
|
10
|
+
== General
|
|
11
|
+
|
|
12
|
+
=== My application hangs and doesn't respond
|
|
13
|
+
|
|
14
|
+
This is commonly caused by one of these issues:
|
|
15
|
+
|
|
16
|
+
* **No work being processed**: Workers are waiting for work but the queue is empty
|
|
17
|
+
* **Worker not returning results**: A worker's `process` method is stuck in an infinite loop
|
|
18
|
+
* **Deadlock**: Multiple workers are waiting on each other
|
|
19
|
+
|
|
20
|
+
.Diagnosing the issue
|
|
21
|
+
----
|
|
22
|
+
# Enable debug mode to see what's happening
|
|
23
|
+
supervisor.debug!
|
|
24
|
+
|
|
25
|
+
# Check the current state
|
|
26
|
+
queue_info = supervisor.inspect_queue
|
|
27
|
+
puts "Queue size: #{queue_info[:size]}"
|
|
28
|
+
puts "Total added: #{queue_info[:total_added]}"
|
|
29
|
+
|
|
30
|
+
# Check worker status
|
|
31
|
+
status = supervisor.workers_status
|
|
32
|
+
puts "Workers: #{status[:total]} total, #{status[:idle]} idle, #{status[:busy]} busy"
|
|
33
|
+
----
|
|
34
|
+
|
|
35
|
+
.Solutions
|
|
36
|
+
|
|
37
|
+
* If queue size is 0 but total_added > 0, work was already processed
|
|
38
|
+
* If workers are all idle but queue has items, check for worker errors
|
|
39
|
+
* Use `supervisor.results.errors` to see any errors that occurred
|
|
40
|
+
* Use `supervisor.error_reporter.summary` to get error statistics
|
|
41
|
+
|
|
42
|
+
=== Workers are not processing all work items
|
|
43
|
+
|
|
44
|
+
This usually happens when:
|
|
45
|
+
|
|
46
|
+
* Workers encounter errors and don't continue
|
|
47
|
+
* The work queue contains invalid work items
|
|
48
|
+
* Worker pool configuration is incorrect
|
|
49
|
+
|
|
50
|
+
.Check error results
|
|
51
|
+
----
|
|
52
|
+
# After supervisor.run finishes
|
|
53
|
+
errors = supervisor.results.errors
|
|
54
|
+
puts "Failed jobs: #{errors.size}"
|
|
55
|
+
|
|
56
|
+
errors.each do |error_result|
|
|
57
|
+
puts "Work: #{error_result.work.inspect}"
|
|
58
|
+
puts "Error: #{error_result.error}"
|
|
59
|
+
puts "---"
|
|
60
|
+
end
|
|
61
|
+
----
|
|
62
|
+
|
|
63
|
+
.Check error statistics
|
|
64
|
+
----
|
|
65
|
+
report = supervisor.error_reporter.summary
|
|
66
|
+
puts report
|
|
67
|
+
----
|
|
68
|
+
|
|
69
|
+
=== I'm getting "worker_class must be a Class" error
|
|
70
|
+
|
|
71
|
+
This error occurs when you pass a symbol or string instead of the actual class.
|
|
72
|
+
|
|
73
|
+
.Wrong
|
|
74
|
+
----
|
|
75
|
+
supervisor = Fractor::Supervisor.new(
|
|
76
|
+
worker_pools: [
|
|
77
|
+
{ worker_class: :MyWorker } # Wrong - symbol
|
|
78
|
+
# or
|
|
79
|
+
{ worker_class: "MyWorker" } # Wrong - string
|
|
80
|
+
]
|
|
81
|
+
)
|
|
82
|
+
----
|
|
83
|
+
|
|
84
|
+
.Correct
|
|
85
|
+
----
|
|
86
|
+
supervisor = Fractor::Supervisor.new(
|
|
87
|
+
worker_pools: [
|
|
88
|
+
{ worker_class: MyWorker } # Correct - actual class
|
|
89
|
+
]
|
|
90
|
+
)
|
|
91
|
+
----
|
|
92
|
+
|
|
93
|
+
=== I'm getting "must inherit from Fractor::Worker" error
|
|
94
|
+
|
|
95
|
+
Your worker class must inherit from `Fractor::Worker`.
|
|
96
|
+
|
|
97
|
+
.Wrong
|
|
98
|
+
----
|
|
99
|
+
class MyWorker
|
|
100
|
+
def process(work)
|
|
101
|
+
Fractor::WorkResult.new(result: work.input * 2, work: work)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
----
|
|
105
|
+
|
|
106
|
+
.Correct
|
|
107
|
+
----
|
|
108
|
+
class MyWorker < Fractor::Worker
|
|
109
|
+
def process(work)
|
|
110
|
+
Fractor::WorkResult.new(result: work.input * 2, work: work)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
----
|
|
114
|
+
|
|
115
|
+
=== I'm getting "must be an instance of Fractor::Work" error
|
|
116
|
+
|
|
117
|
+
Work items must inherit from `Fractor::Work`.
|
|
118
|
+
|
|
119
|
+
.Wrong
|
|
120
|
+
----
|
|
121
|
+
supervisor.add_work_item(42) # Wrong - raw value
|
|
122
|
+
supervisor.add_work_item({ value: 42 }) # Wrong - hash
|
|
123
|
+
----
|
|
124
|
+
|
|
125
|
+
.Correct
|
|
126
|
+
----
|
|
127
|
+
class MyWork < Fractor::Work
|
|
128
|
+
def initialize(value)
|
|
129
|
+
super({ value: value })
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
supervisor.add_work_item(MyWork.new(42)) # Correct
|
|
134
|
+
----
|
|
135
|
+
|
|
136
|
+
== Performance Issues
|
|
137
|
+
|
|
138
|
+
=== Processing is slower than expected
|
|
139
|
+
|
|
140
|
+
Performance issues can be caused by:
|
|
141
|
+
|
|
142
|
+
* **Too few workers**: Increase worker count
|
|
143
|
+
* **Heavy work items**: Break work into smaller chunks
|
|
144
|
+
* **Worker bottleneck**: Profile worker code for inefficiencies
|
|
145
|
+
|
|
146
|
+
.Enable performance monitoring
|
|
147
|
+
----
|
|
148
|
+
supervisor = Fractor::Supervisor.new(
|
|
149
|
+
worker_pools: [
|
|
150
|
+
{ worker_class: MyWorker, num_workers: 4 }
|
|
151
|
+
],
|
|
152
|
+
enable_performance_monitoring: true
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
# Run workload...
|
|
156
|
+
|
|
157
|
+
# Get performance metrics
|
|
158
|
+
metrics = supervisor.performance_metrics
|
|
159
|
+
puts "Throughput: #{metrics[:throughput]} jobs/sec"
|
|
160
|
+
puts "Average latency: #{metrics[:average_latency]}s"
|
|
161
|
+
puts "P95 latency: #{metrics[:p95_latency]}s"
|
|
162
|
+
puts "Worker utilization: #{metrics[:worker_utilization]}"
|
|
163
|
+
----
|
|
164
|
+
|
|
165
|
+
=== Workers are underutilized
|
|
166
|
+
|
|
167
|
+
If worker utilization is low, consider:
|
|
168
|
+
|
|
169
|
+
* **Increasing batch size**: Send more work items
|
|
170
|
+
* **Reducing worker count**: Match workers to workload
|
|
171
|
+
* **Checking I/O**: Workers may be waiting on external resources
|
|
172
|
+
|
|
173
|
+
.Check worker utilization
|
|
174
|
+
----
|
|
175
|
+
status = supervisor.workers_status
|
|
176
|
+
busy_ratio = status[:busy].to_f / status[:total]
|
|
177
|
+
puts "Worker utilization: #{(busy_ratio * 100).round(2)}%"
|
|
178
|
+
----
|
|
179
|
+
|
|
180
|
+
== Memory Issues
|
|
181
|
+
|
|
182
|
+
=== Memory usage grows over time
|
|
183
|
+
|
|
184
|
+
This can be caused by:
|
|
185
|
+
|
|
186
|
+
* **Large work items**: Work items are retained in results
|
|
187
|
+
* **Result accumulation**: Clear results periodically
|
|
188
|
+
* **Memory leaks in workers**: Profile worker code
|
|
189
|
+
|
|
190
|
+
.Monitor memory usage
|
|
191
|
+
----
|
|
192
|
+
supervisor = Fractor::Supervisor.new(
|
|
193
|
+
worker_pools: [
|
|
194
|
+
{ worker_class: MyWorker }
|
|
195
|
+
],
|
|
196
|
+
enable_performance_monitoring: true
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
# Check metrics
|
|
200
|
+
metrics = supervisor.performance_metrics
|
|
201
|
+
puts "Memory: #{metrics[:memory_mb]} MB"
|
|
202
|
+
----
|
|
203
|
+
|
|
204
|
+
.Clear accumulated results
|
|
205
|
+
----
|
|
206
|
+
# Periodically clear results if you don't need them
|
|
207
|
+
supervisor.results.clear
|
|
208
|
+
supervisor.error_reporter.reset
|
|
209
|
+
----
|
|
210
|
+
|
|
211
|
+
== Continuous Mode Issues
|
|
212
|
+
|
|
213
|
+
=== Continuous server doesn't process new work
|
|
214
|
+
|
|
215
|
+
In continuous mode, work sources must be registered.
|
|
216
|
+
|
|
217
|
+
.Register a work source
|
|
218
|
+
----
|
|
219
|
+
server = Fractor::ContinuousServer.new(
|
|
220
|
+
worker_pools: [
|
|
221
|
+
{ worker_class: MyWorker }
|
|
222
|
+
],
|
|
223
|
+
continuous_mode: true
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
# Register a callback that provides new work
|
|
227
|
+
server.register_work_source do
|
|
228
|
+
# Return new work items or nil/empty array when no work available
|
|
229
|
+
get_work_from_external_source
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
server.run
|
|
233
|
+
----
|
|
234
|
+
|
|
235
|
+
=== Signals aren't being handled correctly
|
|
236
|
+
|
|
237
|
+
Signal handling varies by platform.
|
|
238
|
+
|
|
239
|
+
.Platform-specific signals
|
|
240
|
+
----
|
|
241
|
+
# Unix/Linux/macOS: Send SIGUSR1 for status
|
|
242
|
+
kill -USR1 <pid>
|
|
243
|
+
|
|
244
|
+
# Windows: Try SIGBREAK (Ctrl+Break)
|
|
245
|
+
|
|
246
|
+
# Both: SIGINT (Ctrl+C) and SIGTERM work everywhere
|
|
247
|
+
----
|
|
248
|
+
|
|
249
|
+
== Workflow Issues
|
|
250
|
+
|
|
251
|
+
=== Workflow validation fails
|
|
252
|
+
|
|
253
|
+
Workflow validation catches configuration errors early.
|
|
254
|
+
|
|
255
|
+
.Common workflow errors
|
|
256
|
+
----
|
|
257
|
+
# Missing worker class
|
|
258
|
+
Fractor::Workflow.define("my-workflow") do
|
|
259
|
+
job "process" do
|
|
260
|
+
# Missing: runs MyWorker
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
# Missing job dependencies
|
|
265
|
+
Fractor::Workflow.define("my-workflow") do
|
|
266
|
+
job "transform" do
|
|
267
|
+
runs TransformWorker
|
|
268
|
+
needs "prepare" # "prepare" job doesn't exist
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
----
|
|
272
|
+
|
|
273
|
+
.Use the validation error message
|
|
274
|
+
----
|
|
275
|
+
The error message includes:
|
|
276
|
+
* Which job has the problem
|
|
277
|
+
* What's missing or misconfigured
|
|
278
|
+
* Example of correct usage
|
|
279
|
+
----
|
|
280
|
+
|
|
281
|
+
=== Jobs run in wrong order
|
|
282
|
+
|
|
283
|
+
Workflow jobs run in dependency order, not declaration order.
|
|
284
|
+
|
|
285
|
+
.Specify dependencies explicitly
|
|
286
|
+
----
|
|
287
|
+
Fractor::Workflow.define("my-workflow") do
|
|
288
|
+
job "transform" do
|
|
289
|
+
runs TransformWorker
|
|
290
|
+
needs "prepare" # Will run after "prepare" job
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
job "prepare" do
|
|
294
|
+
runs PrepareWorker
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
job "save" do
|
|
298
|
+
runs SaveWorker
|
|
299
|
+
needs "transform" # Will run last
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
----
|
|
303
|
+
|
|
304
|
+
== Error Handling
|
|
305
|
+
|
|
306
|
+
=== Errors are silently ignored
|
|
307
|
+
|
|
308
|
+
By default, errors are recorded but don't stop processing.
|
|
309
|
+
|
|
310
|
+
.Enable error callbacks
|
|
311
|
+
----
|
|
312
|
+
supervisor = Fractor::Supervisor.new(
|
|
313
|
+
worker_pools: [
|
|
314
|
+
{ worker_class: MyWorker }
|
|
315
|
+
]
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
# Register error callback
|
|
319
|
+
supervisor.on_error do |error_result, worker_name, worker_class|
|
|
320
|
+
puts "Error in #{worker_class}: #{error_result.error}"
|
|
321
|
+
puts "Work item: #{error_result.work.inspect}"
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
supervisor.run
|
|
325
|
+
----
|
|
326
|
+
|
|
327
|
+
=== Retry logic isn't working
|
|
328
|
+
|
|
329
|
+
Retry strategies must be configured correctly.
|
|
330
|
+
|
|
331
|
+
.Configure retry strategy
|
|
332
|
+
----
|
|
333
|
+
Fractor::Workflow.define("my-workflow") do
|
|
334
|
+
job "flaky-job" do
|
|
335
|
+
runs FlakyWorker
|
|
336
|
+
retry_strategy :exponential_backoff, max_attempts: 3, base_delay: 0.1
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
----
|
|
340
|
+
|
|
341
|
+
== Getting Help
|
|
342
|
+
|
|
343
|
+
If you're still stuck:
|
|
344
|
+
|
|
345
|
+
* **Enable debug mode**: `supervisor.debug!` or `FRACTOR_DEBUG=1`
|
|
346
|
+
* **Check error reports**: `supervisor.error_reporter.summary`
|
|
347
|
+
* **Inspect the queue**: `supervisor.inspect_queue`
|
|
348
|
+
* **Check worker status**: `supervisor.workers_status`
|
|
349
|
+
* **Enable performance monitoring**: `enable_performance_monitoring: true`
|
|
350
|
+
* **Review logs**: Check for warning messages and error context
|
|
351
|
+
|
|
352
|
+
.Report issues with:
|
|
353
|
+
|
|
354
|
+
* Error messages and stack traces
|
|
355
|
+
* Worker and Work class definitions
|
|
356
|
+
* Supervisor configuration
|
|
357
|
+
* Debug output with `FRACTOR_DEBUG=1`
|
|
358
|
+
* Performance metrics if relevant
|