ractor-pool 0.4.1 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: faa7b2eb7fcac31583654e4122f532ae419fb009c8fbd5a42f1ddae61c3481c1
4
- data.tar.gz: 98bd5aee0bfbf16c36afa9112b1fde3fa9470b42dbc01792559f04278725b510
3
+ metadata.gz: 2c1dea8867f0e74c842abc4eb14e058be7361695a0e280ac02e57663a6bc461d
4
+ data.tar.gz: f1b7d5d10dbc898a84990907625aeace403cb2d053fcce42947856aba64631e6
5
5
  SHA512:
6
- metadata.gz: 78c0f02d1ab1b7944a78cecf776f25eb86ccb03861fa7b35cb1a163a4eaaddd1124e19d6ad7e342b46a356770bc65932dc9a695466ba105c4b0a2cc9980ca93a
7
- data.tar.gz: a2878afecc2b0586f7fc51983a70bad3a531ac0260c0332d5018e429e0c0c5153a46fd35cd01694b616abb798e3534576b515216d08791c736de99cde5a3131a
6
+ metadata.gz: 3c07ae252a879363467f3d085bfbe573941bc2d733d6ab67a20a18b903f3acdc700404e7abdbacb8bb88b24246b3254898b207fde24605e25049dd1e72dd03e8
7
+ data.tar.gz: 1b4186600d78d0a4df2e84f4cb895de318c9562e5eed118b297e28109c8db3da0f1450230c76c5e1fbf8673e5ed670f74302044d695a8e339b0198c433c55354
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.4.2] - 2026-10-18
4
+
5
+ - Collect worker results and errors on one thread
6
+
3
7
  ## [0.4.1] - 2026-07-20
4
8
 
5
9
  - Name the underlying thread of each worker and coordinator `Ractor`
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class RactorPool
4
- VERSION = "0.4.1"
4
+ VERSION = "0.4.2"
5
5
  end
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 @result_port: Ractor::Port?
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
- @result_port = Ractor::Port.new if result_handler
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
- @result_port&.send(SHUTDOWN, move: true)
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
 
@@ -220,7 +217,7 @@ class RactorPool
220
217
  thread_name = String.new("#{self.class.name} coordinator thread")
221
218
  thread_name << " for #{@name}" if @name
222
219
 
223
- Ractor.new(@size, @result_port, thread_name, name: ractor_name) do |worker_count, result_port, thread_name|
220
+ Ractor.new(@size, @collector_port, thread_name, name: ractor_name) do |worker_count, collector_port, thread_name|
224
221
  Thread.current.name = thread_name
225
222
 
226
223
  work_queue = []
@@ -237,7 +234,7 @@ class RactorPool
237
234
  waiting_workers.each { |worker| worker.send(SHUTDOWN, move: true) }
238
235
  waiting_workers.clear
239
236
  if workers_finished == worker_count
240
- result_port&.send(SHUTDOWN, move: true)
237
+ collector_port&.send(SHUTDOWN, move: true)
241
238
  break
242
239
  end
243
240
 
@@ -251,7 +248,7 @@ class RactorPool
251
248
 
252
249
  workers_finished += 1
253
250
  if workers_finished == worker_count
254
- result_port&.send(SHUTDOWN, move: true)
251
+ collector_port&.send(SHUTDOWN, move: true)
255
252
  break
256
253
  end
257
254
  else
@@ -273,6 +270,9 @@ class RactorPool
273
270
 
274
271
  # @rbs () -> Array[Ractor]
275
272
  def start_workers
273
+ result_port = @collector_port if @result_handler
274
+ error_port = @collector_port unless @on_error
275
+
276
276
  @size.times.map do |index|
277
277
  ractor_name = String.new("#{self.class.name} ractor #{index}")
278
278
  ractor_name << " for #{@name}" if @name
@@ -280,7 +280,7 @@ class RactorPool
280
280
  thread_name = String.new("#{self.class.name} worker thread #{index}")
281
281
  thread_name << " for #{@name}" if @name
282
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|
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
284
  Thread.current.name = thread_name
285
285
 
286
286
  loop do
@@ -294,7 +294,7 @@ class RactorPool
294
294
 
295
295
  result_port&.send(result, move: true)
296
296
  rescue => error
297
- 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)
298
298
  end
299
299
  end
300
300
  end
@@ -303,38 +303,23 @@ class RactorPool
303
303
 
304
304
  # @rbs () -> Thread?
305
305
  def start_collector
306
- return unless @result_handler
306
+ return unless @collector_port
307
307
 
308
308
  thread_name = String.new("#{self.class.name} collector thread")
309
309
  thread_name << " for #{@name}" if @name
310
310
 
311
- Thread.new(@result_port, @result_handler, thread_name) do |result_port, result_handler, name|
312
- Thread.current.name = name
313
-
314
- loop do
315
- result = result_port.receive
316
- break if result == SHUTDOWN
317
-
318
- result_handler.call(result)
319
- end
320
- end
321
- end
322
-
323
- # @rbs () -> Thread?
324
- def start_error_collector
325
- return if @on_error
326
-
327
- thread_name = String.new("#{self.class.name} error collector thread")
328
- thread_name << " for #{@name}" if @name
329
-
330
- Thread.new(@error_port, thread_name) do |error_port, name|
311
+ Thread.new(@collector_port, @result_handler, thread_name) do |collector_port, result_handler, name|
331
312
  Thread.current.name = name
332
313
 
333
314
  loop do
334
- message = error_port.receive
335
- break if message == SHUTDOWN
336
-
337
- 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
338
323
  end
339
324
  end
340
325
  end
@@ -51,7 +51,16 @@ class RactorPool
51
51
 
52
52
  SHUTDOWN: ::Symbol
53
53
 
54
- @error_collector: Thread?
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
- @error_port: Ractor::Port?
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.1
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.10
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