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,290 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: default
|
|
3
|
+
title: Getting started
|
|
4
|
+
nav_order: 2
|
|
5
|
+
---
|
|
6
|
+
= Getting started
|
|
7
|
+
|
|
8
|
+
== Choosing your mode
|
|
9
|
+
|
|
10
|
+
Fractor supports two operating modes, each optimized for different use cases:
|
|
11
|
+
|
|
12
|
+
[cols="1,2,2",options="header"]
|
|
13
|
+
|===
|
|
14
|
+
|Mode |Best for |Key characteristics
|
|
15
|
+
|
|
16
|
+
|Pipeline Mode
|
|
17
|
+
|Batch processing, one-time jobs
|
|
18
|
+
|Finite duration, predefined work, batch result collection
|
|
19
|
+
|
|
20
|
+
|Continuous Mode
|
|
21
|
+
|Long-running servers, streaming
|
|
22
|
+
|Indefinite duration, dynamic work arrival, callback-based results
|
|
23
|
+
|===
|
|
24
|
+
|
|
25
|
+
=== When to use Pipeline Mode
|
|
26
|
+
|
|
27
|
+
Choose Pipeline Mode when:
|
|
28
|
+
|
|
29
|
+
* You have a complete dataset to process upfront
|
|
30
|
+
* Processing has a clear start and end
|
|
31
|
+
* You need all results aggregated after completion
|
|
32
|
+
* The task is one-time or scheduled periodically
|
|
33
|
+
|
|
34
|
+
Examples: File processing, data transformations, batch jobs, ETL pipelines
|
|
35
|
+
|
|
36
|
+
=== When to use Continuous Mode
|
|
37
|
+
|
|
38
|
+
Choose Continuous Mode when:
|
|
39
|
+
|
|
40
|
+
* Work arrives over time from external sources
|
|
41
|
+
* Your application runs as a long-lived server
|
|
42
|
+
* You need to process items as they arrive
|
|
43
|
+
* Results should be handled immediately via callbacks
|
|
44
|
+
|
|
45
|
+
Examples: Chat servers, web servers, background job processors, event streams
|
|
46
|
+
|
|
47
|
+
== Quick start: Pipeline Mode
|
|
48
|
+
|
|
49
|
+
=== Step 1: Define your Work class
|
|
50
|
+
|
|
51
|
+
[source,ruby]
|
|
52
|
+
----
|
|
53
|
+
require 'fractor'
|
|
54
|
+
|
|
55
|
+
class MyWork < Fractor::Work
|
|
56
|
+
def initialize(value)
|
|
57
|
+
super({ value: value })
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def value
|
|
61
|
+
input[:value]
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
----
|
|
65
|
+
|
|
66
|
+
=== Step 2: Define your Worker class
|
|
67
|
+
|
|
68
|
+
[source,ruby]
|
|
69
|
+
----
|
|
70
|
+
class MyWorker < Fractor::Worker
|
|
71
|
+
def process(work)
|
|
72
|
+
result = work.value * 2
|
|
73
|
+
|
|
74
|
+
Fractor::WorkResult.new(result: result, work: work)
|
|
75
|
+
rescue => e
|
|
76
|
+
Fractor::WorkResult.new(error: e.message, work: work)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
----
|
|
80
|
+
|
|
81
|
+
=== Step 3: Create and run the Supervisor
|
|
82
|
+
|
|
83
|
+
The Supervisor class orchestrates the entire framework, managing worker Ractors, distributing work, and collecting results.
|
|
84
|
+
|
|
85
|
+
[source,ruby]
|
|
86
|
+
----
|
|
87
|
+
# Create supervisor
|
|
88
|
+
supervisor = Fractor::Supervisor.new(
|
|
89
|
+
worker_pools: [
|
|
90
|
+
{ worker_class: MyWorker } # Auto-detects number of workers
|
|
91
|
+
]
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
# Add work items
|
|
95
|
+
supervisor.add_work_items([
|
|
96
|
+
MyWork.new(1),
|
|
97
|
+
MyWork.new(2),
|
|
98
|
+
MyWork.new(3)
|
|
99
|
+
])
|
|
100
|
+
|
|
101
|
+
# Run processing
|
|
102
|
+
supervisor.run
|
|
103
|
+
|
|
104
|
+
# Access results
|
|
105
|
+
puts "Results: #{supervisor.results.results.map(&:result)}"
|
|
106
|
+
# => Results: [2, 4, 6]
|
|
107
|
+
----
|
|
108
|
+
|
|
109
|
+
==== Instance-based configuration (for multi-gem usage)
|
|
110
|
+
|
|
111
|
+
If your application uses Fractor alongside other gems that also use Fractor, you can use instance-based configuration to avoid global state pollution:
|
|
112
|
+
|
|
113
|
+
[source,ruby]
|
|
114
|
+
----
|
|
115
|
+
# Use instance-specific logger to avoid polluting global state
|
|
116
|
+
my_logger = Logger.new(STDOUT)
|
|
117
|
+
supervisor = Fractor::Supervisor.new(
|
|
118
|
+
worker_pools: [
|
|
119
|
+
{ worker_class: MyWorker }
|
|
120
|
+
],
|
|
121
|
+
logger: my_logger
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
# Enable tracing for this specific supervisor
|
|
125
|
+
supervisor = Fractor::Supervisor.new(
|
|
126
|
+
worker_pools: [
|
|
127
|
+
{ worker_class: MyWorker }
|
|
128
|
+
],
|
|
129
|
+
tracer_enabled: true,
|
|
130
|
+
tracer_stream: File.open("trace.log", "w")
|
|
131
|
+
)
|
|
132
|
+
----
|
|
133
|
+
|
|
134
|
+
==== Test isolation
|
|
135
|
+
|
|
136
|
+
When testing Fractor code, use `Fractor.reset!` before each test to ensure clean state:
|
|
137
|
+
|
|
138
|
+
[source,ruby]
|
|
139
|
+
----
|
|
140
|
+
RSpec.configure do |config|
|
|
141
|
+
config.before(:each) do
|
|
142
|
+
Fractor.reset! # Resets global logger and tracer state
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
----
|
|
146
|
+
|
|
147
|
+
That's it! You now have parallel processing working.
|
|
148
|
+
|
|
149
|
+
== Quick start: Continuous Mode
|
|
150
|
+
|
|
151
|
+
=== Step 1: Define Work and Worker classes
|
|
152
|
+
|
|
153
|
+
[source,ruby]
|
|
154
|
+
----
|
|
155
|
+
require 'fractor'
|
|
156
|
+
|
|
157
|
+
class MessageWork < Fractor::Work
|
|
158
|
+
def initialize(client_id, message)
|
|
159
|
+
super({ client_id: client_id, message: message })
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def client_id
|
|
163
|
+
input[:client_id]
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def message
|
|
167
|
+
input[:message]
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
class MessageWorker < Fractor::Worker
|
|
172
|
+
def process(work)
|
|
173
|
+
processed = "Echo: #{work.message}"
|
|
174
|
+
|
|
175
|
+
Fractor::WorkResult.new(
|
|
176
|
+
result: { client_id: work.client_id, response: processed },
|
|
177
|
+
work: work
|
|
178
|
+
)
|
|
179
|
+
rescue => e
|
|
180
|
+
Fractor::WorkResult.new(error: e.message, work: work)
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
----
|
|
184
|
+
|
|
185
|
+
=== Step 2: Create WorkQueue and ContinuousServer
|
|
186
|
+
|
|
187
|
+
[source,ruby]
|
|
188
|
+
----
|
|
189
|
+
# Create thread-safe work queue
|
|
190
|
+
work_queue = Fractor::WorkQueue.new
|
|
191
|
+
|
|
192
|
+
# Create continuous server with callbacks
|
|
193
|
+
server = Fractor::ContinuousServer.new(
|
|
194
|
+
worker_pools: [
|
|
195
|
+
{ worker_class: MessageWorker, num_workers: 4 }
|
|
196
|
+
],
|
|
197
|
+
work_queue: work_queue
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
# Define result handlers
|
|
201
|
+
server.on_result do |result|
|
|
202
|
+
puts "Response: #{result.result[:response]}"
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
server.on_error do |error_result|
|
|
206
|
+
puts "Error: #{error_result.error}"
|
|
207
|
+
end
|
|
208
|
+
----
|
|
209
|
+
|
|
210
|
+
=== Step 3: Run server and add work
|
|
211
|
+
|
|
212
|
+
[source,ruby]
|
|
213
|
+
----
|
|
214
|
+
# Start server in background
|
|
215
|
+
server_thread = Thread.new { server.run }
|
|
216
|
+
|
|
217
|
+
# Add work dynamically
|
|
218
|
+
work_queue << MessageWork.new(1, "Hello")
|
|
219
|
+
work_queue << MessageWork.new(2, "World")
|
|
220
|
+
|
|
221
|
+
# Server runs indefinitely
|
|
222
|
+
# Use Ctrl+C for graceful shutdown
|
|
223
|
+
----
|
|
224
|
+
|
|
225
|
+
== Common patterns
|
|
226
|
+
|
|
227
|
+
=== Auto-detection vs explicit worker count
|
|
228
|
+
|
|
229
|
+
[source,ruby]
|
|
230
|
+
----
|
|
231
|
+
# Auto-detect (recommended)
|
|
232
|
+
supervisor = Fractor::Supervisor.new(
|
|
233
|
+
worker_pools: [
|
|
234
|
+
{ worker_class: MyWorker } # Uses Etc.nprocessors
|
|
235
|
+
]
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
# Explicit count
|
|
239
|
+
supervisor = Fractor::Supervisor.new(
|
|
240
|
+
worker_pools: [
|
|
241
|
+
{ worker_class: MyWorker, num_workers: 4 }
|
|
242
|
+
]
|
|
243
|
+
)
|
|
244
|
+
----
|
|
245
|
+
|
|
246
|
+
=== Multiple worker pools
|
|
247
|
+
|
|
248
|
+
[source,ruby]
|
|
249
|
+
----
|
|
250
|
+
supervisor = Fractor::Supervisor.new(
|
|
251
|
+
worker_pools: [
|
|
252
|
+
{ worker_class: FastWorker, num_workers: 8 },
|
|
253
|
+
{ worker_class: SlowWorker, num_workers: 2 }
|
|
254
|
+
]
|
|
255
|
+
)
|
|
256
|
+
----
|
|
257
|
+
|
|
258
|
+
=== Error handling
|
|
259
|
+
|
|
260
|
+
[source,ruby]
|
|
261
|
+
----
|
|
262
|
+
class MyWorker < Fractor::Worker
|
|
263
|
+
def process(work)
|
|
264
|
+
# Validate input
|
|
265
|
+
if work.value < 0
|
|
266
|
+
return Fractor::WorkResult.new(
|
|
267
|
+
error: "Negative values not allowed",
|
|
268
|
+
work: work
|
|
269
|
+
)
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
# Process
|
|
273
|
+
result = work.value * 2
|
|
274
|
+
Fractor::WorkResult.new(result: result, work: work)
|
|
275
|
+
rescue => e
|
|
276
|
+
# Catch unexpected errors
|
|
277
|
+
Fractor::WorkResult.new(error: e.message, work: work)
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
----
|
|
281
|
+
|
|
282
|
+
== Next steps
|
|
283
|
+
|
|
284
|
+
* Learn about link:core-concepts/[Core Concepts] - Component details and interactions
|
|
285
|
+
* Read link:../architecture/[Architecture Guide] - System design and implementation
|
|
286
|
+
* Read link:design-principles/[Design Principles] - Philosophy and rationale
|
|
287
|
+
* Explore link:../guides/pipeline-mode/[Pipeline Mode] in detail
|
|
288
|
+
* Explore link:../guides/continuous-mode/[Continuous Mode] in detail
|
|
289
|
+
* Try link:../features/workflows/[Workflows] for complex processing
|
|
290
|
+
* See link:../reference/examples/[Examples] for real-world patterns
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: default
|
|
3
|
+
title: Installation
|
|
4
|
+
nav_order: 3
|
|
5
|
+
---
|
|
6
|
+
= Installation
|
|
7
|
+
|
|
8
|
+
== System requirements
|
|
9
|
+
|
|
10
|
+
Fractor requires Ruby 3.0 or later. It relies on Ractor, which is available in
|
|
11
|
+
Ruby 3.0+.
|
|
12
|
+
|
|
13
|
+
Fractor supports:
|
|
14
|
+
|
|
15
|
+
* **Ruby 3.0 - 3.x**: Full support using `Ractor.yield` for message passing
|
|
16
|
+
* **Ruby 4.0+**: Full support using `Ractor::Port` for improved communication patterns
|
|
17
|
+
|
|
18
|
+
The user-facing API is identical across both versions. Fractor automatically
|
|
19
|
+
detects your Ruby version and uses the appropriate internal implementation. See
|
|
20
|
+
link:architecture.adoc#ruby-version-compatibility[Architecture: Ruby Version Compatibility]
|
|
21
|
+
for details on the internal differences.
|
|
22
|
+
|
|
23
|
+
To check your Ruby version:
|
|
24
|
+
|
|
25
|
+
[source,sh]
|
|
26
|
+
----
|
|
27
|
+
ruby --version
|
|
28
|
+
----
|
|
29
|
+
|
|
30
|
+
If you need to install or upgrade Ruby, see https://www.ruby-lang.org/en/downloads/.
|
|
31
|
+
|
|
32
|
+
== Installation methods
|
|
33
|
+
|
|
34
|
+
=== Using RubyGems
|
|
35
|
+
|
|
36
|
+
Install Fractor directly from RubyGems:
|
|
37
|
+
|
|
38
|
+
[source,sh]
|
|
39
|
+
----
|
|
40
|
+
gem install fractor
|
|
41
|
+
----
|
|
42
|
+
|
|
43
|
+
=== Using Bundler
|
|
44
|
+
|
|
45
|
+
Add this line to your application's `Gemfile`:
|
|
46
|
+
|
|
47
|
+
[source,ruby]
|
|
48
|
+
----
|
|
49
|
+
gem 'fractor'
|
|
50
|
+
----
|
|
51
|
+
|
|
52
|
+
Then execute:
|
|
53
|
+
|
|
54
|
+
[source,sh]
|
|
55
|
+
----
|
|
56
|
+
bundle install
|
|
57
|
+
----
|
|
58
|
+
|
|
59
|
+
=== From source
|
|
60
|
+
|
|
61
|
+
To install Fractor from source:
|
|
62
|
+
|
|
63
|
+
[source,sh]
|
|
64
|
+
----
|
|
65
|
+
git clone https://github.com/metanorma/fractor.git
|
|
66
|
+
cd fractor
|
|
67
|
+
bundle install
|
|
68
|
+
bundle exec rake install
|
|
69
|
+
----
|
|
70
|
+
|
|
71
|
+
== Verifying installation
|
|
72
|
+
|
|
73
|
+
After installation, verify that Fractor is available:
|
|
74
|
+
|
|
75
|
+
[source,ruby]
|
|
76
|
+
----
|
|
77
|
+
require 'fractor'
|
|
78
|
+
puts Fractor::VERSION
|
|
79
|
+
----
|
|
80
|
+
|
|
81
|
+
== Troubleshooting
|
|
82
|
+
|
|
83
|
+
=== Ruby version issues
|
|
84
|
+
|
|
85
|
+
If you encounter errors about Ractor not being available, ensure you're using
|
|
86
|
+
Ruby 3.0 or later:
|
|
87
|
+
|
|
88
|
+
[source,sh]
|
|
89
|
+
----
|
|
90
|
+
ruby --version
|
|
91
|
+
# Should show 3.0.0 or higher
|
|
92
|
+
----
|
|
93
|
+
|
|
94
|
+
=== Installation errors
|
|
95
|
+
|
|
96
|
+
If you encounter permission errors during installation:
|
|
97
|
+
|
|
98
|
+
[source,sh]
|
|
99
|
+
----
|
|
100
|
+
# Use --user-install flag
|
|
101
|
+
gem install fractor --user-install
|
|
102
|
+
|
|
103
|
+
# Or use a Ruby version manager like rbenv or rvm
|
|
104
|
+
----
|
|
105
|
+
|
|
106
|
+
=== Platform-specific issues
|
|
107
|
+
|
|
108
|
+
==== macOS
|
|
109
|
+
|
|
110
|
+
On macOS, you may need to install Ruby via Homebrew if the system Ruby is too old:
|
|
111
|
+
|
|
112
|
+
[source,sh]
|
|
113
|
+
----
|
|
114
|
+
brew install ruby
|
|
115
|
+
----
|
|
116
|
+
|
|
117
|
+
==== Windows
|
|
118
|
+
|
|
119
|
+
On Windows, use RubyInstaller (https://rubyinstaller.org/) to install Ruby 3.0+.
|
|
120
|
+
|
|
121
|
+
==== Linux
|
|
122
|
+
|
|
123
|
+
Most Linux distributions provide Ruby in their package managers:
|
|
124
|
+
|
|
125
|
+
[source,sh]
|
|
126
|
+
----
|
|
127
|
+
# Ubuntu/Debian
|
|
128
|
+
sudo apt-get install ruby-full
|
|
129
|
+
|
|
130
|
+
# Fedora/CentOS
|
|
131
|
+
sudo dnf install ruby
|
|
132
|
+
|
|
133
|
+
# Arch Linux
|
|
134
|
+
sudo pacman -S ruby
|
|
135
|
+
----
|
|
136
|
+
|
|
137
|
+
=== Getting help
|
|
138
|
+
|
|
139
|
+
If you encounter issues not covered here:
|
|
140
|
+
|
|
141
|
+
* Check the https://github.com/metanorma/fractor/issues[GitHub Issues]
|
|
142
|
+
* Open a new issue with details about your environment and error messages
|
|
143
|
+
* Join the discussion in the https://github.com/metanorma/fractor/discussions[GitHub Discussions]
|