ractor-pool 0.4.0 → 0.4.2
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/CHANGELOG.md +8 -0
- data/lib/ractor-pool/version.rb +1 -1
- data/lib/ractor-pool.rb +34 -39
- data/sig/generated/ractor-pool.rbs +11 -7
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2c1dea8867f0e74c842abc4eb14e058be7361695a0e280ac02e57663a6bc461d
|
|
4
|
+
data.tar.gz: f1b7d5d10dbc898a84990907625aeace403cb2d053fcce42947856aba64631e6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3c07ae252a879363467f3d085bfbe573941bc2d733d6ab67a20a18b903f3acdc700404e7abdbacb8bb88b24246b3254898b207fde24605e25049dd1e72dd03e8
|
|
7
|
+
data.tar.gz: 1b4186600d78d0a4df2e84f4cb895de318c9562e5eed118b297e28109c8db3da0f1450230c76c5e1fbf8673e5ed670f74302044d695a8e339b0198c433c55354
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.4.2] - 2026-10-18
|
|
4
|
+
|
|
5
|
+
- Collect worker results and errors on one thread
|
|
6
|
+
|
|
7
|
+
## [0.4.1] - 2026-07-20
|
|
8
|
+
|
|
9
|
+
- Name the underlying thread of each worker and coordinator `Ractor`
|
|
10
|
+
|
|
3
11
|
## [0.4.0] - 2026-05-20
|
|
4
12
|
|
|
5
13
|
- Add `:round_robin` dispatch strategy
|
data/lib/ractor-pool/version.rb
CHANGED
data/lib/ractor-pool.rb
CHANGED
|
@@ -59,6 +59,9 @@ class RactorPool
|
|
|
59
59
|
SHUTDOWN = :shutdown
|
|
60
60
|
private_constant :SHUTDOWN
|
|
61
61
|
|
|
62
|
+
WorkerError = Data.define(:full_message)
|
|
63
|
+
private_constant :WorkerError
|
|
64
|
+
|
|
62
65
|
# @rbs @size: Integer
|
|
63
66
|
# @rbs @worker: ^(untyped) -> untyped
|
|
64
67
|
# @rbs @strategy: Symbol
|
|
@@ -68,12 +71,10 @@ class RactorPool
|
|
|
68
71
|
# @rbs @in_flight: Atom[Integer]
|
|
69
72
|
# @rbs @shutdown: Atom[bool]
|
|
70
73
|
# @rbs @next_worker_index: Atom[Integer]?
|
|
71
|
-
# @rbs @
|
|
72
|
-
# @rbs @error_port: Ractor::Port?
|
|
74
|
+
# @rbs @collector_port: Ractor::Port?
|
|
73
75
|
# @rbs @coordinator: Ractor?
|
|
74
76
|
# @rbs @workers: Array[Ractor]
|
|
75
77
|
# @rbs @collector: Thread?
|
|
76
|
-
# @rbs @error_collector: Thread?
|
|
77
78
|
|
|
78
79
|
# Creates a new RactorPool with the specified number of workers.
|
|
79
80
|
#
|
|
@@ -121,12 +122,10 @@ class RactorPool
|
|
|
121
122
|
@shutdown = Atom.new(false)
|
|
122
123
|
@next_worker_index = Atom.new(-1) if size > 1 && strategy == :round_robin
|
|
123
124
|
|
|
124
|
-
@
|
|
125
|
-
@error_port = Ractor::Port.new unless on_error
|
|
125
|
+
@collector_port = Ractor::Port.new if result_handler || !on_error
|
|
126
126
|
@coordinator = start_coordinator if size > 1 && strategy == :coordinator
|
|
127
127
|
@workers = start_workers
|
|
128
128
|
@collector = start_collector
|
|
129
|
-
@error_collector = start_error_collector
|
|
130
129
|
end
|
|
131
130
|
|
|
132
131
|
# Queues a work item to be processed by an available worker.
|
|
@@ -203,10 +202,8 @@ class RactorPool
|
|
|
203
202
|
else
|
|
204
203
|
@workers.each { |worker| worker.send(SHUTDOWN, move: true) }
|
|
205
204
|
@workers.each(&:join)
|
|
206
|
-
@
|
|
205
|
+
@collector_port&.send(SHUTDOWN, move: true)
|
|
207
206
|
end
|
|
208
|
-
@error_port&.send(SHUTDOWN, move: true)
|
|
209
|
-
@error_collector&.join
|
|
210
207
|
@collector&.join
|
|
211
208
|
end
|
|
212
209
|
|
|
@@ -217,7 +214,12 @@ class RactorPool
|
|
|
217
214
|
ractor_name = String.new("#{self.class.name} coordinator ractor")
|
|
218
215
|
ractor_name << " for #{@name}" if @name
|
|
219
216
|
|
|
220
|
-
|
|
217
|
+
thread_name = String.new("#{self.class.name} coordinator thread")
|
|
218
|
+
thread_name << " for #{@name}" if @name
|
|
219
|
+
|
|
220
|
+
Ractor.new(@size, @collector_port, thread_name, name: ractor_name) do |worker_count, collector_port, thread_name|
|
|
221
|
+
Thread.current.name = thread_name
|
|
222
|
+
|
|
221
223
|
work_queue = []
|
|
222
224
|
waiting_workers = []
|
|
223
225
|
shutdown_received = false
|
|
@@ -232,7 +234,7 @@ class RactorPool
|
|
|
232
234
|
waiting_workers.each { |worker| worker.send(SHUTDOWN, move: true) }
|
|
233
235
|
waiting_workers.clear
|
|
234
236
|
if workers_finished == worker_count
|
|
235
|
-
|
|
237
|
+
collector_port&.send(SHUTDOWN, move: true)
|
|
236
238
|
break
|
|
237
239
|
end
|
|
238
240
|
|
|
@@ -246,7 +248,7 @@ class RactorPool
|
|
|
246
248
|
|
|
247
249
|
workers_finished += 1
|
|
248
250
|
if workers_finished == worker_count
|
|
249
|
-
|
|
251
|
+
collector_port&.send(SHUTDOWN, move: true)
|
|
250
252
|
break
|
|
251
253
|
end
|
|
252
254
|
else
|
|
@@ -268,11 +270,19 @@ class RactorPool
|
|
|
268
270
|
|
|
269
271
|
# @rbs () -> Array[Ractor]
|
|
270
272
|
def start_workers
|
|
273
|
+
result_port = @collector_port if @result_handler
|
|
274
|
+
error_port = @collector_port unless @on_error
|
|
275
|
+
|
|
271
276
|
@size.times.map do |index|
|
|
272
277
|
ractor_name = String.new("#{self.class.name} ractor #{index}")
|
|
273
278
|
ractor_name << " for #{@name}" if @name
|
|
274
279
|
|
|
275
|
-
|
|
280
|
+
thread_name = String.new("#{self.class.name} worker thread #{index}")
|
|
281
|
+
thread_name << " for #{@name}" if @name
|
|
282
|
+
|
|
283
|
+
Ractor.new(@worker, @on_error, error_port, @coordinator, result_port, thread_name, name: ractor_name) do |worker, on_error, error_port, coordinator, result_port, thread_name|
|
|
284
|
+
Thread.current.name = thread_name
|
|
285
|
+
|
|
276
286
|
loop do
|
|
277
287
|
coordinator&.send(Ractor.current, move: true)
|
|
278
288
|
|
|
@@ -284,7 +294,7 @@ class RactorPool
|
|
|
284
294
|
|
|
285
295
|
result_port&.send(result, move: true)
|
|
286
296
|
rescue => error
|
|
287
|
-
on_error ? on_error.call(error) : error_port.send(error.full_message, move: true)
|
|
297
|
+
on_error ? on_error.call(error) : error_port.send(WorkerError.new(full_message: error.full_message), move: true)
|
|
288
298
|
end
|
|
289
299
|
end
|
|
290
300
|
end
|
|
@@ -293,38 +303,23 @@ class RactorPool
|
|
|
293
303
|
|
|
294
304
|
# @rbs () -> Thread?
|
|
295
305
|
def start_collector
|
|
296
|
-
return unless @
|
|
306
|
+
return unless @collector_port
|
|
297
307
|
|
|
298
308
|
thread_name = String.new("#{self.class.name} collector thread")
|
|
299
309
|
thread_name << " for #{@name}" if @name
|
|
300
310
|
|
|
301
|
-
Thread.new(@
|
|
311
|
+
Thread.new(@collector_port, @result_handler, thread_name) do |collector_port, result_handler, name|
|
|
302
312
|
Thread.current.name = name
|
|
303
313
|
|
|
304
314
|
loop do
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
# @rbs () -> Thread?
|
|
314
|
-
def start_error_collector
|
|
315
|
-
return if @on_error
|
|
316
|
-
|
|
317
|
-
thread_name = String.new("#{self.class.name} error collector thread")
|
|
318
|
-
thread_name << " for #{@name}" if @name
|
|
319
|
-
|
|
320
|
-
Thread.new(@error_port, thread_name) do |error_port, name|
|
|
321
|
-
Thread.current.name = name
|
|
322
|
-
|
|
323
|
-
loop do
|
|
324
|
-
message = error_port.receive
|
|
325
|
-
break if message == SHUTDOWN
|
|
326
|
-
|
|
327
|
-
warn message
|
|
315
|
+
case message = collector_port.receive
|
|
316
|
+
when SHUTDOWN
|
|
317
|
+
break
|
|
318
|
+
when WorkerError
|
|
319
|
+
warn message.full_message
|
|
320
|
+
else
|
|
321
|
+
result_handler.call(message)
|
|
322
|
+
end
|
|
328
323
|
end
|
|
329
324
|
end
|
|
330
325
|
end
|
|
@@ -51,7 +51,16 @@ class RactorPool
|
|
|
51
51
|
|
|
52
52
|
SHUTDOWN: ::Symbol
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
class WorkerError < Data
|
|
55
|
+
attr_reader full_message(): untyped
|
|
56
|
+
|
|
57
|
+
def self.new: (untyped full_message) -> instance
|
|
58
|
+
| (full_message: untyped) -> instance
|
|
59
|
+
|
|
60
|
+
def self.members: () -> [ :full_message ]
|
|
61
|
+
|
|
62
|
+
def members: () -> [ :full_message ]
|
|
63
|
+
end
|
|
55
64
|
|
|
56
65
|
@collector: Thread?
|
|
57
66
|
|
|
@@ -59,9 +68,7 @@ class RactorPool
|
|
|
59
68
|
|
|
60
69
|
@coordinator: Ractor?
|
|
61
70
|
|
|
62
|
-
@
|
|
63
|
-
|
|
64
|
-
@result_port: Ractor::Port?
|
|
71
|
+
@collector_port: Ractor::Port?
|
|
65
72
|
|
|
66
73
|
@next_worker_index: Atom[Integer]?
|
|
67
74
|
|
|
@@ -154,7 +161,4 @@ class RactorPool
|
|
|
154
161
|
|
|
155
162
|
# @rbs () -> Thread?
|
|
156
163
|
def start_collector: () -> Thread?
|
|
157
|
-
|
|
158
|
-
# @rbs () -> Thread?
|
|
159
|
-
def start_error_collector: () -> Thread?
|
|
160
164
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ractor-pool
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.4.
|
|
4
|
+
version: 0.4.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Joshua Young
|
|
@@ -73,7 +73,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
73
73
|
- !ruby/object:Gem::Version
|
|
74
74
|
version: '0'
|
|
75
75
|
requirements: []
|
|
76
|
-
rubygems_version: 4.0.
|
|
76
|
+
rubygems_version: 4.0.20
|
|
77
77
|
specification_version: 4
|
|
78
78
|
summary: A thread-safe, lock-free pool of Ractor workers with coordinator or round-robin
|
|
79
79
|
dispatch for distributing work
|