fractor 0.1.6 → 0.1.8
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,347 @@
|
|
|
1
|
+
= Simple Example - Getting Started with Fractor
|
|
2
|
+
|
|
3
|
+
== Purpose
|
|
4
|
+
|
|
5
|
+
Provides the most basic introduction to Fractor, demonstrating fundamental concepts with minimal complexity to help new users get started quickly.
|
|
6
|
+
|
|
7
|
+
== Focus
|
|
8
|
+
|
|
9
|
+
This example focuses on the essential building blocks:
|
|
10
|
+
|
|
11
|
+
* Creating custom `Work` classes to encapsulate work items
|
|
12
|
+
* Creating custom `Worker` classes to process work
|
|
13
|
+
* Setting up a `Supervisor` to manage parallel processing
|
|
14
|
+
* Adding work items and running the supervisor
|
|
15
|
+
* Processing results and handling errors
|
|
16
|
+
* Auto-detection of available processors
|
|
17
|
+
|
|
18
|
+
== Architecture
|
|
19
|
+
|
|
20
|
+
.Basic Fractor Architecture
|
|
21
|
+
[source]
|
|
22
|
+
----
|
|
23
|
+
Main Program
|
|
24
|
+
│
|
|
25
|
+
├─→ Create Work Items (MyWork)
|
|
26
|
+
│ │
|
|
27
|
+
│ └─→ MyWork { value: 1 }
|
|
28
|
+
│ MyWork { value: 2 }
|
|
29
|
+
│ ...
|
|
30
|
+
│ MyWork { value: 10 }
|
|
31
|
+
│
|
|
32
|
+
├─→ Create Supervisor
|
|
33
|
+
│ │
|
|
34
|
+
│ └─→ Worker Pool Configuration
|
|
35
|
+
│ │
|
|
36
|
+
│ └─→ MyWorker (auto-detect CPU count)
|
|
37
|
+
│
|
|
38
|
+
├─→ Add Work Items
|
|
39
|
+
│ │
|
|
40
|
+
│ └─→ supervisor.add_work_items(work_items)
|
|
41
|
+
│
|
|
42
|
+
├─→ Run Supervisor
|
|
43
|
+
│ │
|
|
44
|
+
│ └─→ Parallel Processing
|
|
45
|
+
│ │
|
|
46
|
+
│ ├─→ Ractor 1 (MyWorker) ─→ Process work
|
|
47
|
+
│ ├─→ Ractor 2 (MyWorker) ─→ Process work
|
|
48
|
+
│ ├─→ Ractor 3 (MyWorker) ─→ Process work
|
|
49
|
+
│ └─→ Ractor N (MyWorker) ─→ Process work
|
|
50
|
+
│ │
|
|
51
|
+
│ └─→ Results Aggregator
|
|
52
|
+
│ │
|
|
53
|
+
│ ├─→ Successful Results
|
|
54
|
+
│ └─→ Error Results
|
|
55
|
+
│
|
|
56
|
+
└─→ Display Results
|
|
57
|
+
│
|
|
58
|
+
├─→ supervisor.results (all results)
|
|
59
|
+
└─→ supervisor.results.errors (failed items)
|
|
60
|
+
----
|
|
61
|
+
|
|
62
|
+
.Data Flow
|
|
63
|
+
[source]
|
|
64
|
+
----
|
|
65
|
+
Work Items Worker Processing Results
|
|
66
|
+
──────────────────────────────────────────────────────────────────
|
|
67
|
+
|
|
68
|
+
MyWork(1) ─┐
|
|
69
|
+
MyWork(2) ─┤
|
|
70
|
+
MyWork(3) ─┤
|
|
71
|
+
MyWork(4) ─┼─→ Work Queue ─→ Ractor Pool ─→ WorkResult(2)
|
|
72
|
+
MyWork(5) ─┤ (Supervisor) (Workers) WorkResult(4)
|
|
73
|
+
MyWork(6) ─┤ WorkResult(6)
|
|
74
|
+
MyWork(7) ─┤ WorkResult(8)
|
|
75
|
+
MyWork(8) ─┤ ...
|
|
76
|
+
MyWork(9) ─┤ WorkError(5)
|
|
77
|
+
MyWork(10) ─┘ WorkResult(20)
|
|
78
|
+
----
|
|
79
|
+
|
|
80
|
+
== Key Components
|
|
81
|
+
|
|
82
|
+
=== Work Class
|
|
83
|
+
|
|
84
|
+
The `Work` class encapsulates input data for processing:
|
|
85
|
+
|
|
86
|
+
[source,ruby]
|
|
87
|
+
----
|
|
88
|
+
class MyWork < Fractor::Work
|
|
89
|
+
def initialize(value)
|
|
90
|
+
super({ value: value }) # <1>
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def value
|
|
94
|
+
input[:value] # <2>
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def to_s
|
|
98
|
+
"MyWork: #{value}" # <3>
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
----
|
|
102
|
+
<1> Store data in input hash using `super`
|
|
103
|
+
<2> Access stored data via `input` hash
|
|
104
|
+
<3> Provide string representation for debugging
|
|
105
|
+
|
|
106
|
+
Key points:
|
|
107
|
+
|
|
108
|
+
* Inherit from `Fractor::Work`
|
|
109
|
+
* Store all data in the `input` hash
|
|
110
|
+
* Provide accessor methods for convenience
|
|
111
|
+
* Include `to_s` method for debugging
|
|
112
|
+
|
|
113
|
+
=== Worker Class
|
|
114
|
+
|
|
115
|
+
The `Worker` class processes work items:
|
|
116
|
+
|
|
117
|
+
[source,ruby]
|
|
118
|
+
----
|
|
119
|
+
class MyWorker < Fractor::Worker
|
|
120
|
+
def process(work) # <1>
|
|
121
|
+
# Check work type
|
|
122
|
+
if work.is_a?(MyWork)
|
|
123
|
+
# Handle known error case
|
|
124
|
+
if work.value == 5
|
|
125
|
+
error = StandardError.new('Cannot process value 5')
|
|
126
|
+
return Fractor::WorkResult.new(error: error, work: work) # <2>
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Process successfully
|
|
130
|
+
calculated = work.value * 2
|
|
131
|
+
Fractor::WorkResult.new(result: calculated, work: work) # <3>
|
|
132
|
+
|
|
133
|
+
else
|
|
134
|
+
# Handle unexpected work type
|
|
135
|
+
error = TypeError.new("Unsupported work type: #{work.class}")
|
|
136
|
+
Fractor::WorkResult.new(error: error, work: work)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
----
|
|
141
|
+
<1> Implement `process(work)` method - called by Ractor
|
|
142
|
+
<2> Return `WorkResult` with error for failures
|
|
143
|
+
<3> Return `WorkResult` with result for success
|
|
144
|
+
|
|
145
|
+
Key points:
|
|
146
|
+
|
|
147
|
+
* Inherit from `Fractor::Worker`
|
|
148
|
+
* Implement `process(work)` method
|
|
149
|
+
* Return `Fractor::WorkResult` objects
|
|
150
|
+
* Handle errors gracefully (return error results, don't raise)
|
|
151
|
+
* Support multiple work types if needed
|
|
152
|
+
|
|
153
|
+
=== Supervisor Setup
|
|
154
|
+
|
|
155
|
+
The `Supervisor` manages worker Ractors and distributes work:
|
|
156
|
+
|
|
157
|
+
[source,ruby]
|
|
158
|
+
----
|
|
159
|
+
# Create supervisor with worker pool
|
|
160
|
+
supervisor = Fractor::Supervisor.new(
|
|
161
|
+
worker_pools: [
|
|
162
|
+
{ worker_class: MyWorker } # <1>
|
|
163
|
+
]
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
# Create and add work items
|
|
167
|
+
work_items = (1..10).map { |i| MyWork.new(i) } # <2>
|
|
168
|
+
supervisor.add_work_items(work_items) # <3>
|
|
169
|
+
|
|
170
|
+
# Run the supervisor
|
|
171
|
+
supervisor.run # <4>
|
|
172
|
+
|
|
173
|
+
# Access results
|
|
174
|
+
supervisor.results # <5>
|
|
175
|
+
supervisor.results.errors # <6>
|
|
176
|
+
----
|
|
177
|
+
<1> Define worker pool (auto-detects CPU count)
|
|
178
|
+
<2> Create array of work items
|
|
179
|
+
<3> Add work items to supervisor
|
|
180
|
+
<4> Start processing (blocks until complete)
|
|
181
|
+
<5> Access all results (successful and failed)
|
|
182
|
+
<6> Access only failed results
|
|
183
|
+
|
|
184
|
+
Key points:
|
|
185
|
+
|
|
186
|
+
* Worker pools default to auto-detected CPU count
|
|
187
|
+
* Can specify `num_workers` explicitly if needed
|
|
188
|
+
* `run` blocks until all work is complete
|
|
189
|
+
* Results are aggregated in `supervisor.results`
|
|
190
|
+
|
|
191
|
+
== Usage
|
|
192
|
+
|
|
193
|
+
Run the example from the project root:
|
|
194
|
+
|
|
195
|
+
[source,shell]
|
|
196
|
+
----
|
|
197
|
+
ruby examples/simple/sample.rb
|
|
198
|
+
|
|
199
|
+
# With debug output
|
|
200
|
+
FRACTOR_DEBUG=1 ruby examples/simple/sample.rb
|
|
201
|
+
----
|
|
202
|
+
|
|
203
|
+
== Expected Output
|
|
204
|
+
|
|
205
|
+
[example]
|
|
206
|
+
====
|
|
207
|
+
[source]
|
|
208
|
+
----
|
|
209
|
+
Processing complete.
|
|
210
|
+
Final Aggregated Results:
|
|
211
|
+
#<Fractor::ResultAggregator:0x... @results=[
|
|
212
|
+
#<Fractor::WorkResult @result=2, @work=#<MyWork: 1>>,
|
|
213
|
+
#<Fractor::WorkResult @result=4, @work=#<MyWork: 2>>,
|
|
214
|
+
#<Fractor::WorkResult @result=6, @work=#<MyWork: 3>>,
|
|
215
|
+
#<Fractor::WorkResult @result=8, @work=#<MyWork: 4>>,
|
|
216
|
+
#<Fractor::WorkResult @result=12, @work=#<MyWork: 6>>,
|
|
217
|
+
#<Fractor::WorkResult @result=14, @work=#<MyWork: 7>>,
|
|
218
|
+
#<Fractor::WorkResult @result=16, @work=#<MyWork: 8>>,
|
|
219
|
+
#<Fractor::WorkResult @result=18, @work=#<MyWork: 9>>,
|
|
220
|
+
#<Fractor::WorkResult @result=20, @work=#<MyWork: 10>>
|
|
221
|
+
], @errors=[...]>
|
|
222
|
+
|
|
223
|
+
Failed Work Items (1):
|
|
224
|
+
Work: MyWork: 5
|
|
225
|
+
Error: StandardError: Cannot process value 5
|
|
226
|
+
----
|
|
227
|
+
====
|
|
228
|
+
|
|
229
|
+
== Learning Points
|
|
230
|
+
|
|
231
|
+
=== Parallel Processing
|
|
232
|
+
|
|
233
|
+
* Fractor automatically distributes work across multiple Ractors
|
|
234
|
+
* Number of Ractors defaults to available CPU cores
|
|
235
|
+
* Work is processed in parallel, improving throughput
|
|
236
|
+
* Order of completion is non-deterministic
|
|
237
|
+
|
|
238
|
+
=== Work Encapsulation
|
|
239
|
+
|
|
240
|
+
* Each work item is a separate object with its input data
|
|
241
|
+
* Work items are isolated from each other
|
|
242
|
+
* Workers process one work item at a time
|
|
243
|
+
* Work items can be of different types (polymorphic)
|
|
244
|
+
|
|
245
|
+
=== Error Handling
|
|
246
|
+
|
|
247
|
+
* Errors don't stop the entire processing
|
|
248
|
+
* Failed work items are tracked separately
|
|
249
|
+
* Workers return error results, not exceptions
|
|
250
|
+
* System continues processing remaining work
|
|
251
|
+
|
|
252
|
+
=== Auto-Detection
|
|
253
|
+
|
|
254
|
+
* When `num_workers` is not specified, Fractor auto-detects CPU count
|
|
255
|
+
* Uses `Etc.nprocessors` to determine available cores
|
|
256
|
+
* Optimal for CPU-bound tasks
|
|
257
|
+
* Can be overridden if needed:
|
|
258
|
+
+
|
|
259
|
+
[source,ruby]
|
|
260
|
+
----
|
|
261
|
+
supervisor = Fractor::Supervisor.new(
|
|
262
|
+
worker_pools: [
|
|
263
|
+
{ worker_class: MyWorker, num_workers: 4 }
|
|
264
|
+
]
|
|
265
|
+
)
|
|
266
|
+
----
|
|
267
|
+
|
|
268
|
+
=== Result Aggregation
|
|
269
|
+
|
|
270
|
+
* All results are collected in `supervisor.results`
|
|
271
|
+
* Successful results accessible via `results.results`
|
|
272
|
+
* Failed results accessible via `results.errors`
|
|
273
|
+
* Each result contains both the output and original work item
|
|
274
|
+
|
|
275
|
+
== Common Patterns
|
|
276
|
+
|
|
277
|
+
=== Multiple Work Types
|
|
278
|
+
|
|
279
|
+
Process different types of work with the same worker:
|
|
280
|
+
|
|
281
|
+
[source,ruby]
|
|
282
|
+
----
|
|
283
|
+
class MyWorker < Fractor::Worker
|
|
284
|
+
def process(work)
|
|
285
|
+
if work.is_a?(MyWork)
|
|
286
|
+
# Process MyWork
|
|
287
|
+
Fractor::WorkResult.new(result: work.value * 2, work: work)
|
|
288
|
+
elsif work.is_a?(OtherWork)
|
|
289
|
+
# Process OtherWork differently
|
|
290
|
+
Fractor::WorkResult.new(result: "Processed: #{work.value}", work: work)
|
|
291
|
+
else
|
|
292
|
+
# Handle unknown types
|
|
293
|
+
error = TypeError.new("Unsupported work type: #{work.class}")
|
|
294
|
+
Fractor::WorkResult.new(error: error, work: work)
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
----
|
|
299
|
+
|
|
300
|
+
=== Conditional Processing
|
|
301
|
+
|
|
302
|
+
Make decisions based on work item data:
|
|
303
|
+
|
|
304
|
+
[source,ruby]
|
|
305
|
+
----
|
|
306
|
+
def process(work)
|
|
307
|
+
if work.value < 0
|
|
308
|
+
error = ArgumentError.new('Value must be positive')
|
|
309
|
+
return Fractor::WorkResult.new(error: error, work: work)
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
if work.value > 100
|
|
313
|
+
# Heavy processing for large values
|
|
314
|
+
result = complex_calculation(work.value)
|
|
315
|
+
else
|
|
316
|
+
# Simple processing for small values
|
|
317
|
+
result = work.value * 2
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
Fractor::WorkResult.new(result: result, work: work)
|
|
321
|
+
end
|
|
322
|
+
----
|
|
323
|
+
|
|
324
|
+
=== Debugging
|
|
325
|
+
|
|
326
|
+
Use `ENV['FRACTOR_DEBUG']` to enable debug output:
|
|
327
|
+
|
|
328
|
+
[source,ruby]
|
|
329
|
+
----
|
|
330
|
+
def process(work)
|
|
331
|
+
puts "Working on '#{work.inspect}'" if ENV['FRACTOR_DEBUG']
|
|
332
|
+
|
|
333
|
+
# Processing logic...
|
|
334
|
+
|
|
335
|
+
Fractor::WorkResult.new(result: result, work: work)
|
|
336
|
+
end
|
|
337
|
+
----
|
|
338
|
+
|
|
339
|
+
== Next Steps
|
|
340
|
+
|
|
341
|
+
After understanding the basics, explore more advanced examples:
|
|
342
|
+
|
|
343
|
+
* link:../auto_detection/README.adoc[Auto Detection] - CPU auto-detection in detail
|
|
344
|
+
* link:../multi_work_type/README.adoc[Multi Work Type] - Handling multiple work types
|
|
345
|
+
* link:../specialized_workers/README.adoc[Specialized Workers] - Worker pools for different tasks
|
|
346
|
+
* link:../pipeline_processing/README.adoc[Pipeline Processing] - Sequential processing stages
|
|
347
|
+
* link:../workflow/README.adoc[Workflow System] - GitHub Actions-style workflows
|