fractor 0.1.3 → 0.1.4
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 +13 -23
- data/README.adoc +71 -5
- data/examples/auto_detection/README.adoc +52 -0
- data/examples/auto_detection/auto_detection.rb +170 -0
- data/examples/simple/sample.rb +34 -2
- data/lib/fractor/supervisor.rb +14 -4
- data/lib/fractor/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 842123f96e07a7da2fd523396b9c3caa74e39ff3bda280fa8473c306a26d809c
|
4
|
+
data.tar.gz: 6bb92bd2ad43a2a7a3fac8f50056c2a0a7e16d1b79e914dc390c458d3ee3ea97
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3f0613742f3e736514ef88cafde83a35d68e02178a034565b3c36aad00f7f6463fec3f4aad37bdc5dc65dd2c12c7c033b29009db97704e8c9cf4c67607f8f58a
|
7
|
+
data.tar.gz: d8e466f3244f0a88456f9c42388590a6c67e3e552b4b3e7d769217b32ddf12b2595264944241590e4c4f0ec098a79ac02bfe39622ba3d4f95cd037bd3d23e064
|
data/.rubocop_todo.yml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config`
|
3
|
-
# on 2025-
|
3
|
+
# on 2025-10-09 11:44:45 UTC using RuboCop version 1.75.4.
|
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
|
@@ -14,11 +14,6 @@ Lint/ConstantDefinitionInBlock:
|
|
14
14
|
- 'spec/fractor/integration_spec.rb'
|
15
15
|
- 'spec/fractor/work_spec.rb'
|
16
16
|
|
17
|
-
# Offense count: 1
|
18
|
-
Lint/DuplicateMethods:
|
19
|
-
Exclude:
|
20
|
-
- 'lib/fractor/supervisor.rb'
|
21
|
-
|
22
17
|
# Offense count: 1
|
23
18
|
Lint/HashCompareByIdentity:
|
24
19
|
Exclude:
|
@@ -30,43 +25,44 @@ Lint/MissingSuper:
|
|
30
25
|
Exclude:
|
31
26
|
- 'examples/specialized_workers/specialized_workers.rb'
|
32
27
|
|
33
|
-
# Offense count:
|
28
|
+
# Offense count: 4
|
34
29
|
Lint/RescueException:
|
35
30
|
Exclude:
|
31
|
+
- 'lib/fractor/supervisor.rb'
|
36
32
|
- 'lib/fractor/wrapped_ractor.rb'
|
37
33
|
|
38
|
-
# Offense count:
|
34
|
+
# Offense count: 24
|
39
35
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
|
40
36
|
Metrics/AbcSize:
|
41
37
|
Max: 98
|
42
38
|
|
43
|
-
# Offense count:
|
39
|
+
# Offense count: 15
|
44
40
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
45
41
|
# AllowedMethods: refine
|
46
42
|
Metrics/BlockLength:
|
47
|
-
Max:
|
43
|
+
Max: 142
|
48
44
|
|
49
|
-
# Offense count:
|
45
|
+
# Offense count: 4
|
50
46
|
# Configuration parameters: CountComments, CountAsOne.
|
51
47
|
Metrics/ClassLength:
|
52
|
-
Max:
|
48
|
+
Max: 171
|
53
49
|
|
54
|
-
# Offense count:
|
50
|
+
# Offense count: 9
|
55
51
|
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
56
52
|
Metrics/CyclomaticComplexity:
|
57
53
|
Max: 37
|
58
54
|
|
59
|
-
# Offense count:
|
55
|
+
# Offense count: 46
|
60
56
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
61
57
|
Metrics/MethodLength:
|
62
|
-
Max:
|
58
|
+
Max: 78
|
63
59
|
|
64
60
|
# Offense count: 1
|
65
61
|
# Configuration parameters: Max, CountKeywordArgs.
|
66
62
|
Metrics/ParameterLists:
|
67
63
|
MaxOptionalParameters: 4
|
68
64
|
|
69
|
-
# Offense count:
|
65
|
+
# Offense count: 6
|
70
66
|
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
71
67
|
Metrics/PerceivedComplexity:
|
72
68
|
Max: 37
|
@@ -84,13 +80,7 @@ Style/Documentation:
|
|
84
80
|
- 'test/**/*'
|
85
81
|
- 'examples/hierarchical_hasher/hierarchical_hasher.rb'
|
86
82
|
|
87
|
-
# Offense count:
|
88
|
-
# This cop supports safe autocorrection (--autocorrect).
|
89
|
-
Style/IfUnlessModifier:
|
90
|
-
Exclude:
|
91
|
-
- 'lib/fractor/supervisor.rb'
|
92
|
-
|
93
|
-
# Offense count: 6
|
83
|
+
# Offense count: 12
|
94
84
|
# This cop supports safe autocorrection (--autocorrect).
|
95
85
|
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings.
|
96
86
|
# URISchemes: http, https
|
data/README.adoc
CHANGED
@@ -267,16 +267,25 @@ The Supervisor also manages the work queue and the ResultAggregator, which
|
|
267
267
|
collects and organizes all results from the workers.
|
268
268
|
|
269
269
|
To set up the Supervisor, you specify worker pools, each containing a Worker class
|
270
|
-
and the number of workers to create.
|
271
|
-
|
272
|
-
|
270
|
+
and optionally the number of workers to create. If you don't specify `num_workers`,
|
271
|
+
Fractor will automatically detect the number of available processors on your system
|
272
|
+
and use that value. You can create multiple worker pools with different worker types
|
273
|
+
to handle different kinds of work. Each worker pool can process any type of Work
|
274
|
+
object that inherits from Fractor::Work.
|
273
275
|
|
274
276
|
[source,ruby]
|
275
277
|
----
|
276
|
-
# Create the supervisor
|
278
|
+
# Create the supervisor with auto-detected number of workers
|
277
279
|
supervisor = Fractor::Supervisor.new(
|
278
280
|
worker_pools: [
|
279
|
-
{ worker_class: MyWorker
|
281
|
+
{ worker_class: MyWorker } # Number of workers auto-detected
|
282
|
+
]
|
283
|
+
)
|
284
|
+
|
285
|
+
# Or explicitly specify the number of workers
|
286
|
+
supervisor = Fractor::Supervisor.new(
|
287
|
+
worker_pools: [
|
288
|
+
{ worker_class: MyWorker, num_workers: 4 } # Explicitly use 4 workers
|
280
289
|
]
|
281
290
|
)
|
282
291
|
|
@@ -619,6 +628,47 @@ supervisor = Fractor::Supervisor.new(
|
|
619
628
|
)
|
620
629
|
----
|
621
630
|
|
631
|
+
==== Worker auto-detection
|
632
|
+
|
633
|
+
Fractor automatically detects the number of available processors on your system
|
634
|
+
and uses that value when `num_workers` is not specified. This provides optimal
|
635
|
+
resource utilization across different deployment environments without requiring
|
636
|
+
manual configuration.
|
637
|
+
|
638
|
+
[source,ruby]
|
639
|
+
----
|
640
|
+
# Auto-detect number of workers (recommended for most cases)
|
641
|
+
supervisor = Fractor::Supervisor.new(
|
642
|
+
worker_pools: [
|
643
|
+
{ worker_class: MyWorker } # Will use number of available processors
|
644
|
+
]
|
645
|
+
)
|
646
|
+
|
647
|
+
# Explicitly set number of workers (useful for specific requirements)
|
648
|
+
supervisor = Fractor::Supervisor.new(
|
649
|
+
worker_pools: [
|
650
|
+
{ worker_class: MyWorker, num_workers: 4 } # Always use exactly 4 workers
|
651
|
+
]
|
652
|
+
)
|
653
|
+
|
654
|
+
# Mix auto-detection and explicit configuration
|
655
|
+
supervisor = Fractor::Supervisor.new(
|
656
|
+
worker_pools: [
|
657
|
+
{ worker_class: FastWorker }, # Auto-detected
|
658
|
+
{ worker_class: HeavyWorker, num_workers: 2 } # Explicitly 2 workers
|
659
|
+
]
|
660
|
+
)
|
661
|
+
----
|
662
|
+
|
663
|
+
The auto-detection uses Ruby's `Etc.nprocessors` which returns the number of
|
664
|
+
available processors. If detection fails for any reason, it falls back to 2
|
665
|
+
workers.
|
666
|
+
|
667
|
+
[TIP]
|
668
|
+
* Use auto-detection for portable code that adapts to different environments
|
669
|
+
* Explicitly set `num_workers` when you need precise control over resource usage
|
670
|
+
* Consider system load and other factors when choosing explicit values
|
671
|
+
|
622
672
|
==== Adding work
|
623
673
|
|
624
674
|
You can add work items individually or in batches:
|
@@ -897,8 +947,24 @@ Key features:
|
|
897
947
|
* Simple Supervisor setup
|
898
948
|
* Parallel processing of work items
|
899
949
|
* Error handling and result aggregation
|
950
|
+
* Auto-detection of available processors
|
900
951
|
* Graceful shutdown on completion
|
901
952
|
|
953
|
+
=== Auto-detection example
|
954
|
+
|
955
|
+
The Auto-Detection Example (link:examples/auto_detection/[examples/auto_detection/])
|
956
|
+
demonstrates Fractor's automatic worker detection feature. It shows how to use
|
957
|
+
auto-detection, explicit configuration, and mixed approaches for controlling
|
958
|
+
the number of workers.
|
959
|
+
|
960
|
+
Key features:
|
961
|
+
|
962
|
+
* Automatic detection of available processors
|
963
|
+
* Comparison of auto-detection vs explicit configuration
|
964
|
+
* Mixed configuration with multiple worker pools
|
965
|
+
* Best practices for worker configuration
|
966
|
+
* Portable code that adapts to different environments
|
967
|
+
|
902
968
|
=== Hierarchical hasher
|
903
969
|
|
904
970
|
The Hierarchical Hasher example
|
@@ -0,0 +1,52 @@
|
|
1
|
+
= Auto-Detection Example
|
2
|
+
|
3
|
+
This example demonstrates Fractor's automatic worker detection feature.
|
4
|
+
|
5
|
+
== Purpose
|
6
|
+
|
7
|
+
Shows how Fractor can automatically detect the number of available processors on your system and create the optimal number of workers without manual configuration.
|
8
|
+
|
9
|
+
== What This Demonstrates
|
10
|
+
|
11
|
+
* How Fractor automatically detects the number of available processors
|
12
|
+
* Comparison between auto-detection and explicit worker configuration
|
13
|
+
* Mixed configuration (some pools with auto-detection, some explicit)
|
14
|
+
* How to verify the number of workers being used
|
15
|
+
|
16
|
+
== When to Use Auto-Detection
|
17
|
+
|
18
|
+
* For portable code that adapts to different environments
|
19
|
+
* When you want optimal resource utilization without manual tuning
|
20
|
+
* For development where the number of cores varies across machines
|
21
|
+
|
22
|
+
== When to Set Explicit Values
|
23
|
+
|
24
|
+
* When you need precise control over resource usage
|
25
|
+
* For production environments with specific requirements
|
26
|
+
* When limiting workers due to memory or other constraints
|
27
|
+
|
28
|
+
== Running the Example
|
29
|
+
|
30
|
+
[source,shell]
|
31
|
+
----
|
32
|
+
ruby examples/auto_detection/auto_detection.rb
|
33
|
+
----
|
34
|
+
|
35
|
+
== Expected Output
|
36
|
+
|
37
|
+
The script will:
|
38
|
+
|
39
|
+
1. Display the number of processors detected on your system
|
40
|
+
2. Run three examples:
|
41
|
+
* Example 1: Auto-detection (uses all available processors)
|
42
|
+
* Example 2: Explicit configuration (uses exactly 4 workers)
|
43
|
+
* Example 3: Mixed configuration (combines both approaches)
|
44
|
+
3. Show results from processing work items in parallel
|
45
|
+
4. Provide a summary of benefits for each approach
|
46
|
+
|
47
|
+
== Key Takeaways
|
48
|
+
|
49
|
+
* Auto-detection provides automatic adaptation to different environments
|
50
|
+
* Explicit configuration provides precise control when needed
|
51
|
+
* You can mix both approaches in the same supervisor
|
52
|
+
* Best practice: use auto-detection for development, tune for production if needed
|
@@ -0,0 +1,170 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# =============================================================================
|
5
|
+
# Auto-Detection Example
|
6
|
+
# =============================================================================
|
7
|
+
#
|
8
|
+
# This example demonstrates Fractor's automatic worker detection feature.
|
9
|
+
#
|
10
|
+
# WHAT THIS DEMONSTRATES:
|
11
|
+
# - How Fractor automatically detects the number of available processors
|
12
|
+
# - Comparison between auto-detection and explicit worker configuration
|
13
|
+
# - Mixed configuration (some pools with auto-detection, some explicit)
|
14
|
+
# - How to verify the number of workers being used
|
15
|
+
#
|
16
|
+
# WHEN TO USE AUTO-DETECTION:
|
17
|
+
# - For portable code that adapts to different environments
|
18
|
+
# - When you want optimal resource utilization without manual tuning
|
19
|
+
# - For development where the number of cores varies across machines
|
20
|
+
#
|
21
|
+
# WHEN TO SET EXPLICIT VALUES:
|
22
|
+
# - When you need precise control over resource usage
|
23
|
+
# - For production environments with specific requirements
|
24
|
+
# - When limiting workers due to memory or other constraints
|
25
|
+
#
|
26
|
+
# HOW TO RUN:
|
27
|
+
# ruby examples/auto_detection/auto_detection.rb
|
28
|
+
#
|
29
|
+
# WHAT TO EXPECT:
|
30
|
+
# - The script will show how many processors were auto-detected
|
31
|
+
# - It will create workers based on detection vs explicit configuration
|
32
|
+
# - Results will be processed in parallel across all workers
|
33
|
+
#
|
34
|
+
# =============================================================================
|
35
|
+
|
36
|
+
require_relative "../../lib/fractor"
|
37
|
+
require "etc"
|
38
|
+
|
39
|
+
# Simple work class for demonstration
|
40
|
+
class ComputeWork < Fractor::Work
|
41
|
+
def initialize(value)
|
42
|
+
super({ value: value })
|
43
|
+
end
|
44
|
+
|
45
|
+
def value
|
46
|
+
input[:value]
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_s
|
50
|
+
"ComputeWork: #{value}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Simple worker that squares numbers
|
55
|
+
class ComputeWorker < Fractor::Worker
|
56
|
+
def process(work)
|
57
|
+
result = work.value * work.value
|
58
|
+
Fractor::WorkResult.new(result: result, work: work)
|
59
|
+
rescue StandardError => e
|
60
|
+
Fractor::WorkResult.new(error: e, work: work)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# =============================================================================
|
65
|
+
# DEMONSTRATION
|
66
|
+
# =============================================================================
|
67
|
+
|
68
|
+
puts "=" * 80
|
69
|
+
puts "Fractor Auto-Detection Example"
|
70
|
+
puts "=" * 80
|
71
|
+
puts
|
72
|
+
|
73
|
+
# Show system information
|
74
|
+
num_processors = Etc.nprocessors
|
75
|
+
puts "System Information:"
|
76
|
+
puts " Available processors: #{num_processors}"
|
77
|
+
puts
|
78
|
+
|
79
|
+
# Example 1: Auto-detection (recommended for most cases)
|
80
|
+
puts "-" * 80
|
81
|
+
puts "Example 1: Auto-Detection"
|
82
|
+
puts "-" * 80
|
83
|
+
puts "Creating supervisor WITHOUT specifying num_workers..."
|
84
|
+
puts "Fractor will automatically detect and use #{num_processors} workers"
|
85
|
+
puts
|
86
|
+
|
87
|
+
supervisor1 = Fractor::Supervisor.new(
|
88
|
+
worker_pools: [
|
89
|
+
{ worker_class: ComputeWorker } # No num_workers specified
|
90
|
+
]
|
91
|
+
)
|
92
|
+
|
93
|
+
# Add work items
|
94
|
+
work_items = (1..10).map { |i| ComputeWork.new(i) }
|
95
|
+
supervisor1.add_work_items(work_items)
|
96
|
+
|
97
|
+
puts "Processing 10 work items with auto-detected workers..."
|
98
|
+
supervisor1.run
|
99
|
+
|
100
|
+
puts "Results: #{supervisor1.results.results.map(&:result).sort.join(", ")}"
|
101
|
+
puts "✓ Auto-detection successful!"
|
102
|
+
puts
|
103
|
+
|
104
|
+
# Example 2: Explicit configuration
|
105
|
+
puts "-" * 80
|
106
|
+
puts "Example 2: Explicit Configuration"
|
107
|
+
puts "-" * 80
|
108
|
+
puts "Creating supervisor WITH explicit num_workers=4..."
|
109
|
+
puts
|
110
|
+
|
111
|
+
supervisor2 = Fractor::Supervisor.new(
|
112
|
+
worker_pools: [
|
113
|
+
{ worker_class: ComputeWorker, num_workers: 4 }
|
114
|
+
]
|
115
|
+
)
|
116
|
+
|
117
|
+
supervisor2.add_work_items((11..20).map { |i| ComputeWork.new(i) })
|
118
|
+
|
119
|
+
puts "Processing 10 work items with 4 explicitly configured workers..."
|
120
|
+
supervisor2.run
|
121
|
+
|
122
|
+
puts "Results: #{supervisor2.results.results.map(&:result).sort.join(", ")}"
|
123
|
+
puts "✓ Explicit configuration successful!"
|
124
|
+
puts
|
125
|
+
|
126
|
+
# Example 3: Mixed configuration
|
127
|
+
puts "-" * 80
|
128
|
+
puts "Example 3: Mixed Auto-Detection and Explicit Configuration"
|
129
|
+
puts "-" * 80
|
130
|
+
puts "Creating supervisor with multiple worker pools:"
|
131
|
+
puts " - Pool 1: Auto-detected workers"
|
132
|
+
puts " - Pool 2: 2 explicitly configured workers"
|
133
|
+
puts
|
134
|
+
|
135
|
+
supervisor3 = Fractor::Supervisor.new(
|
136
|
+
worker_pools: [
|
137
|
+
{ worker_class: ComputeWorker }, # Auto-detected
|
138
|
+
{ worker_class: ComputeWorker, num_workers: 2 } # Explicit
|
139
|
+
]
|
140
|
+
)
|
141
|
+
|
142
|
+
supervisor3.add_work_items((21..30).map { |i| ComputeWork.new(i) })
|
143
|
+
|
144
|
+
puts "Processing 10 work items with mixed configuration..."
|
145
|
+
supervisor3.run
|
146
|
+
|
147
|
+
puts "Results: #{supervisor3.results.results.map(&:result).sort.join(", ")}"
|
148
|
+
puts "✓ Mixed configuration successful!"
|
149
|
+
puts
|
150
|
+
|
151
|
+
# Summary
|
152
|
+
puts "=" * 80
|
153
|
+
puts "Summary"
|
154
|
+
puts "=" * 80
|
155
|
+
puts
|
156
|
+
puts "Auto-detection provides:"
|
157
|
+
puts " ✓ Automatic adaptation to different environments"
|
158
|
+
puts " ✓ Optimal resource utilization by default"
|
159
|
+
puts " ✓ Less configuration needed"
|
160
|
+
puts " ✓ Portability across machines with different CPU counts"
|
161
|
+
puts
|
162
|
+
puts "Explicit configuration provides:"
|
163
|
+
puts " ✓ Precise control over worker count"
|
164
|
+
puts " ✓ Ability to limit resource usage"
|
165
|
+
puts " ✓ Predictable behavior in production"
|
166
|
+
puts
|
167
|
+
puts "Best practice: Use auto-detection for development and testing,"
|
168
|
+
puts " then tune explicitly for production if needed."
|
169
|
+
puts
|
170
|
+
puts "=" * 80
|
data/examples/simple/sample.rb
CHANGED
@@ -1,7 +1,38 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
|
4
|
+
# =============================================================================
|
5
|
+
# Simple Example - Getting Started with Fractor
|
6
|
+
# =============================================================================
|
7
|
+
#
|
8
|
+
# This example demonstrates the basic usage of the Fractor framework.
|
9
|
+
#
|
10
|
+
# WHAT THIS DEMONSTRATES:
|
11
|
+
# - How to create a Work class (MyWork) to encapsulate work items
|
12
|
+
# - How to create a Worker class (MyWorker) to process work
|
13
|
+
# - How to set up a Supervisor to manage parallel processing
|
14
|
+
# - Basic error handling in workers
|
15
|
+
# - How to access and display results after processing
|
16
|
+
# - Auto-detection of available processors (num_workers not specified)
|
17
|
+
#
|
18
|
+
# KEY CONCEPTS:
|
19
|
+
# 1. Work Class: Inherits from Fractor::Work, stores input data
|
20
|
+
# 2. Worker Class: Inherits from Fractor::Worker, implements process() method
|
21
|
+
# 3. Supervisor: Manages worker Ractors and distributes work
|
22
|
+
# 4. WorkResult: Contains either successful results or errors
|
23
|
+
#
|
24
|
+
# HOW TO RUN:
|
25
|
+
# ruby examples/simple/sample.rb
|
26
|
+
#
|
27
|
+
# WHAT TO EXPECT:
|
28
|
+
# - Creates work items with values 1-10
|
29
|
+
# - Processes them in parallel using auto-detected number of workers
|
30
|
+
# - Value 5 intentionally produces an error for demonstration
|
31
|
+
# - Displays successful results and error information
|
32
|
+
#
|
33
|
+
# =============================================================================
|
34
|
+
|
35
|
+
require_relative "../../lib/fractor"
|
5
36
|
|
6
37
|
# Client-specific work item implementation inheriting from Fractor::Work
|
7
38
|
class MyWork < Fractor::Work
|
@@ -71,9 +102,10 @@ end
|
|
71
102
|
# MyWorker and MyWork classes.
|
72
103
|
if __FILE__ == $PROGRAM_NAME
|
73
104
|
# Create supervisor, passing the client-specific worker class in a worker pool
|
105
|
+
# Note: num_workers is not specified, so it will auto-detect the number of available processors
|
74
106
|
supervisor = Fractor::Supervisor.new(
|
75
107
|
worker_pools: [
|
76
|
-
{ worker_class: MyWorker
|
108
|
+
{ worker_class: MyWorker } # Worker class without explicit num_workers uses auto-detection
|
77
109
|
]
|
78
110
|
)
|
79
111
|
|
data/lib/fractor/supervisor.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "etc"
|
4
|
+
|
3
5
|
module Fractor
|
4
6
|
# Supervises multiple WrappedRactors, distributes work, and aggregates results.
|
5
7
|
class Supervisor
|
@@ -13,7 +15,7 @@ module Fractor
|
|
13
15
|
def initialize(worker_pools: [], continuous_mode: false)
|
14
16
|
@worker_pools = worker_pools.map do |pool_config|
|
15
17
|
worker_class = pool_config[:worker_class]
|
16
|
-
num_workers = pool_config[:num_workers] ||
|
18
|
+
num_workers = pool_config[:num_workers] || detect_num_workers
|
17
19
|
|
18
20
|
raise ArgumentError, "#{worker_class} must inherit from Fractor::Worker" unless worker_class < Fractor::Worker
|
19
21
|
|
@@ -46,9 +48,6 @@ module Fractor
|
|
46
48
|
puts "Work item added. Initial work count: #{@total_work_count}, Queue size: #{@work_queue.size}"
|
47
49
|
end
|
48
50
|
|
49
|
-
# Alias for better naming
|
50
|
-
alias add_work_item add_work_item
|
51
|
-
|
52
51
|
# Adds multiple work items to the queue.
|
53
52
|
# Each item must be an instance of Fractor::Work or a subclass.
|
54
53
|
def add_work_items(works)
|
@@ -226,6 +225,17 @@ module Fractor
|
|
226
225
|
|
227
226
|
private
|
228
227
|
|
228
|
+
# Detects the number of available processors on the system.
|
229
|
+
# Returns the number of processors, or 2 as a fallback if detection fails.
|
230
|
+
def detect_num_workers
|
231
|
+
num_processors = Etc.nprocessors
|
232
|
+
puts "Auto-detected #{num_processors} available processors" if ENV["FRACTOR_DEBUG"]
|
233
|
+
num_processors
|
234
|
+
rescue StandardError => e
|
235
|
+
puts "Failed to detect processors: #{e.message}. Using default of 2 workers." if ENV["FRACTOR_DEBUG"]
|
236
|
+
2
|
237
|
+
end
|
238
|
+
|
229
239
|
# Helper method to send the next available work item to a specific Ractor.
|
230
240
|
def send_next_work_if_available(wrapped_ractor)
|
231
241
|
# Ensure the wrapped_ractor instance is valid and its underlying ractor is not closed
|
data/lib/fractor/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fractor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ronald Tse
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-10-09 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Fractor is a lightweight Ruby framework designed to simplify the process
|
14
14
|
of distributing computational work across multiple Ractors.
|
@@ -24,6 +24,8 @@ files:
|
|
24
24
|
- CODE_OF_CONDUCT.md
|
25
25
|
- README.adoc
|
26
26
|
- Rakefile
|
27
|
+
- examples/auto_detection/README.adoc
|
28
|
+
- examples/auto_detection/auto_detection.rb
|
27
29
|
- examples/hierarchical_hasher/README.adoc
|
28
30
|
- examples/hierarchical_hasher/hierarchical_hasher.rb
|
29
31
|
- examples/multi_work_type/README.adoc
|