omq 0.15.3 → 0.15.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/CHANGELOG.md +16 -1
- data/lib/omq/engine.rb +22 -17
- data/lib/omq/routing/staging_queue.rb +9 -3
- data/lib/omq/socket.rb +1 -1
- data/lib/omq/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3357d4050a4f44b5c440026bc6ec9100cd34a64307f04fe8eab88ab219617cbc
|
|
4
|
+
data.tar.gz: b507113e3df663fbb27b805370be466795d00f0fd483e62a7936156a74047a5e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7d8dbffe8678966f753c0679543b7933cfe986dfd0fb7cb15be2aa824b99064f7a42e45fe73dd1e9d63e59fbaeeafe8b03f14e7a75078858d4f80d636cb3001e
|
|
7
|
+
data.tar.gz: 4ff71015d8434c0199b5c0f55312d8ee55defa7b2ae1d8dd526c6938cb20c77332a207848fbeae3e383a7d832cc305bd3030e2d36685c65483ddc1155e58bea3
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 0.15.4 — 2026-04-08
|
|
4
|
+
|
|
5
|
+
- **Lazy routing initialization** — the routing strategy is now created on
|
|
6
|
+
first use (bind, connect, send, or receive) instead of eagerly in the
|
|
7
|
+
constructor. This allows socket option setters (`send_hwm=`, `recv_hwm=`)
|
|
8
|
+
to take effect before internal queue sizing.
|
|
9
|
+
- **Prefetch byte limit** — `dequeue_recv_batch` now stops at 1 MB total,
|
|
10
|
+
not just 64 messages. Prevents large messages from filling the prefetch
|
|
11
|
+
buffer with hundreds of megabytes.
|
|
12
|
+
- **Bound staging queue `@head`** — `StagingQueue#prepend` now drops messages
|
|
13
|
+
when at capacity, preventing unbounded growth during reconnect cycles.
|
|
14
|
+
- **Bound monitor queue** — `Socket#monitor` uses a `LimitedQueue(64)` instead
|
|
15
|
+
of an unbounded queue, preventing memory growth when verbose monitoring
|
|
16
|
+
can't keep up with message rate.
|
|
17
|
+
|
|
18
|
+
### Unreleased
|
|
4
19
|
|
|
5
20
|
- **Auto-freeze on bind/connect** — `#bind` and `#connect` now call
|
|
6
21
|
`OMQ.freeze_for_ractors!` automatically, freezing `CONNECTION_LOST`,
|
data/lib/omq/engine.rb
CHANGED
|
@@ -42,9 +42,11 @@ module OMQ
|
|
|
42
42
|
attr_reader :options
|
|
43
43
|
|
|
44
44
|
|
|
45
|
-
# @return [Routing] routing strategy
|
|
45
|
+
# @return [Routing] routing strategy (created lazily on first access)
|
|
46
46
|
#
|
|
47
|
-
|
|
47
|
+
def routing
|
|
48
|
+
@routing ||= Routing.for(@socket_type).new(self)
|
|
49
|
+
end
|
|
48
50
|
|
|
49
51
|
|
|
50
52
|
# @return [String, nil] last bound endpoint
|
|
@@ -63,7 +65,7 @@ module OMQ
|
|
|
63
65
|
def initialize(socket_type, options)
|
|
64
66
|
@socket_type = socket_type
|
|
65
67
|
@options = options
|
|
66
|
-
@routing =
|
|
68
|
+
@routing = nil
|
|
67
69
|
@connections = {} # connection => ConnectionRecord
|
|
68
70
|
@dialed = Set.new # endpoints we called connect() on (reconnect intent)
|
|
69
71
|
@listeners = []
|
|
@@ -225,7 +227,7 @@ module OMQ
|
|
|
225
227
|
pipe = @connection_wrapper.call(pipe) if @connection_wrapper
|
|
226
228
|
@connections[pipe] = ConnectionRecord.new(endpoint: endpoint, done: nil)
|
|
227
229
|
emit_monitor_event(:handshake_succeeded, endpoint: endpoint)
|
|
228
|
-
|
|
230
|
+
routing.connection_added(pipe)
|
|
229
231
|
@peer_connected.resolve(pipe)
|
|
230
232
|
end
|
|
231
233
|
|
|
@@ -237,28 +239,31 @@ module OMQ
|
|
|
237
239
|
#
|
|
238
240
|
def dequeue_recv
|
|
239
241
|
raise @fatal_error if @fatal_error
|
|
240
|
-
msg =
|
|
242
|
+
msg = routing.recv_queue.dequeue
|
|
241
243
|
raise @fatal_error if msg.nil? && @fatal_error
|
|
242
244
|
msg
|
|
243
245
|
end
|
|
244
246
|
|
|
245
247
|
|
|
246
|
-
# Dequeues up to +max+ messages
|
|
247
|
-
# drains non-blocking.
|
|
248
|
+
# Dequeues up to +max+ messages or +max_bytes+ total. Blocks
|
|
249
|
+
# on the first, then drains non-blocking.
|
|
248
250
|
#
|
|
249
|
-
# @param max [Integer]
|
|
251
|
+
# @param max [Integer] message count limit
|
|
252
|
+
# @param max_bytes [Integer] byte size limit
|
|
250
253
|
# @return [Array<Array<String>>]
|
|
251
254
|
#
|
|
252
|
-
def dequeue_recv_batch(max)
|
|
255
|
+
def dequeue_recv_batch(max, max_bytes: 1 << 20)
|
|
253
256
|
raise @fatal_error if @fatal_error
|
|
254
|
-
queue =
|
|
257
|
+
queue = routing.recv_queue
|
|
255
258
|
msg = queue.dequeue
|
|
256
259
|
raise @fatal_error if msg.nil? && @fatal_error
|
|
257
260
|
batch = [msg]
|
|
258
|
-
|
|
261
|
+
bytes = msg.sum(&:bytesize)
|
|
262
|
+
while batch.size < max && bytes < max_bytes
|
|
259
263
|
msg = queue.dequeue(timeout: 0)
|
|
260
264
|
break unless msg
|
|
261
265
|
batch << msg
|
|
266
|
+
bytes += msg.sum(&:bytesize)
|
|
262
267
|
end
|
|
263
268
|
batch
|
|
264
269
|
end
|
|
@@ -268,7 +273,7 @@ module OMQ
|
|
|
268
273
|
# pending {#dequeue_recv} with a nil return value.
|
|
269
274
|
#
|
|
270
275
|
def dequeue_recv_sentinel
|
|
271
|
-
|
|
276
|
+
routing.recv_queue.push(nil)
|
|
272
277
|
end
|
|
273
278
|
|
|
274
279
|
|
|
@@ -280,7 +285,7 @@ module OMQ
|
|
|
280
285
|
#
|
|
281
286
|
def enqueue_send(parts)
|
|
282
287
|
raise @fatal_error if @fatal_error
|
|
283
|
-
|
|
288
|
+
routing.enqueue(parts)
|
|
284
289
|
end
|
|
285
290
|
|
|
286
291
|
|
|
@@ -305,7 +310,7 @@ module OMQ
|
|
|
305
310
|
#
|
|
306
311
|
def connection_lost(connection)
|
|
307
312
|
entry = @connections.delete(connection)
|
|
308
|
-
|
|
313
|
+
routing.connection_removed(connection)
|
|
309
314
|
connection.close
|
|
310
315
|
emit_monitor_event(:disconnected, endpoint: entry&.endpoint)
|
|
311
316
|
entry&.done&.resolve(true)
|
|
@@ -369,7 +374,7 @@ module OMQ
|
|
|
369
374
|
rescue => wrapped
|
|
370
375
|
wrapped
|
|
371
376
|
end
|
|
372
|
-
|
|
377
|
+
routing.recv_queue.push(nil) rescue nil
|
|
373
378
|
@peer_connected.resolve(nil) rescue nil
|
|
374
379
|
end
|
|
375
380
|
|
|
@@ -502,14 +507,14 @@ module OMQ
|
|
|
502
507
|
conns = @connections.filter_map { |conn, e| conn if e.endpoint == endpoint }
|
|
503
508
|
conns.each do |conn|
|
|
504
509
|
@connections.delete(conn)
|
|
505
|
-
|
|
510
|
+
routing.connection_removed(conn)
|
|
506
511
|
conn.close
|
|
507
512
|
end
|
|
508
513
|
end
|
|
509
514
|
|
|
510
515
|
|
|
511
516
|
def stop_tasks
|
|
512
|
-
|
|
517
|
+
routing.stop rescue nil
|
|
513
518
|
@tasks.each { |t| t.stop rescue nil }
|
|
514
519
|
@tasks.clear
|
|
515
520
|
end
|
|
@@ -12,7 +12,8 @@ module OMQ
|
|
|
12
12
|
# @param max [Integer, nil] capacity (nil or 0 = unbounded)
|
|
13
13
|
#
|
|
14
14
|
def initialize(max = nil)
|
|
15
|
-
@
|
|
15
|
+
@max = (max && max > 0) ? max : nil
|
|
16
|
+
@queue = @max ? Async::LimitedQueue.new(@max) : Async::Queue.new
|
|
16
17
|
@head = []
|
|
17
18
|
@mu = Mutex.new
|
|
18
19
|
end
|
|
@@ -30,13 +31,18 @@ module OMQ
|
|
|
30
31
|
|
|
31
32
|
|
|
32
33
|
# Inserts a message at the front (for re-staging after a
|
|
33
|
-
# failed drain).
|
|
34
|
+
# failed drain). Drops the message if the staging queue is
|
|
35
|
+
# already at capacity (messages sent to a peer that disconnected
|
|
36
|
+
# may be lost -- same as ZMQ).
|
|
34
37
|
#
|
|
35
38
|
# @param msg [Array<String>]
|
|
36
39
|
# @return [void]
|
|
37
40
|
#
|
|
38
41
|
def prepend(msg)
|
|
39
|
-
@mu.synchronize
|
|
42
|
+
@mu.synchronize do
|
|
43
|
+
return if @max && @head.size >= @max
|
|
44
|
+
@head.push(msg)
|
|
45
|
+
end
|
|
40
46
|
end
|
|
41
47
|
|
|
42
48
|
|
data/lib/omq/socket.rb
CHANGED
data/lib/omq/version.rb
CHANGED