nnq 0.6.0 → 0.6.1
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 +26 -0
- data/lib/nnq/engine.rb +17 -3
- data/lib/nnq/routing/rep.rb +8 -0
- data/lib/nnq/routing/rep_raw.rb +7 -0
- data/lib/nnq/routing/req.rb +7 -0
- data/lib/nnq/routing/req_raw.rb +7 -0
- data/lib/nnq/routing/respondent.rb +8 -0
- data/lib/nnq/routing/respondent_raw.rb +7 -0
- data/lib/nnq/routing/surveyor.rb +6 -0
- data/lib/nnq/routing/surveyor_raw.rb +6 -0
- data/lib/nnq/socket.rb +2 -1
- data/lib/nnq/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: 19bceda0339689e8850efe39120590002821f5c859eaf33e4ea1065af317bcaa
|
|
4
|
+
data.tar.gz: 2a15dd79b5cf4f8a41c564e89cf40af7296de8765e8e070de12057b4bc0dedf9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1e14a21e6d620df7770c27868f5fdb8ed945fb04137b8817c12fdaa2fdfca1e36a952e6fc4afc5be60562dfd1ff8f43d9d1781ce9a4fb6a1c3a8963cd3738233
|
|
7
|
+
data.tar.gz: 13aae01f03df0b0eca53aa0329d0f2d35b036b4f52744f83033cc46297eae39a60b2c639ad144c9ee3af63cee7d3780c3fff036d30f418e078ccb89253f70761
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.6.1 — 2026-04-15
|
|
4
|
+
|
|
5
|
+
- **Verbose trace (`-vvv`) now fires for cooked REQ/REP/RESPONDENT
|
|
6
|
+
sends.** Cooked `Req#send_request`, `Rep#send_reply`, and
|
|
7
|
+
`Respondent#send_reply` bypass `send_pump` and write to the
|
|
8
|
+
connection directly, so they were never emitting `:message_sent`
|
|
9
|
+
monitor events — `-vvv` only ever showed the `<<` recv side. Each
|
|
10
|
+
now calls `emit_verbose_msg_sent(body)` after the write. Raw
|
|
11
|
+
REQ/REP/RESPONDENT sends get the same treatment (raw surveyor
|
|
12
|
+
already emitted via its per-peer send pump).
|
|
13
|
+
- **Verbose recv previews strip the SP backtrace header.** The recv
|
|
14
|
+
loop used to emit the raw wire body, so `-vvv` traces for
|
|
15
|
+
REQ/REP/SURVEYOR/RESPONDENT showed the 4-byte request/survey id
|
|
16
|
+
(or a multi-word backtrace stack) in front of the payload. Routing
|
|
17
|
+
strategies now expose an optional `preview_body(wire)` hook; the
|
|
18
|
+
engine calls it before emitting `:message_received` so the trace
|
|
19
|
+
shows just the payload.
|
|
20
|
+
- **`Engine#close` drains the monitor queue before cancelling
|
|
21
|
+
tasks.** The monitor consumer fiber lives under the socket-level
|
|
22
|
+
barrier, so `barrier.stop` used to `Async::Stop` it before it had
|
|
23
|
+
a chance to drain trailing events. `close` now emits `:closed`,
|
|
24
|
+
enqueues the nil sentinel, and awaits the stored `monitor_task`
|
|
25
|
+
before stopping the barrier. Fixes flaky `-vvv` traces on
|
|
26
|
+
short-lived sockets where the last `:message_received` event
|
|
27
|
+
would occasionally be lost.
|
|
28
|
+
|
|
3
29
|
## 0.6.0 — 2026-04-15
|
|
4
30
|
|
|
5
31
|
- **NNG-style raw mode for REQ/REP and SURVEYOR/RESPONDENT.** Constructing
|
data/lib/nnq/engine.rb
CHANGED
|
@@ -70,6 +70,10 @@ module NNQ
|
|
|
70
70
|
attr_accessor :monitor_queue
|
|
71
71
|
|
|
72
72
|
|
|
73
|
+
# @return [Async::Task, nil] the monitor consumer task, if any
|
|
74
|
+
attr_accessor :monitor_task
|
|
75
|
+
|
|
76
|
+
|
|
73
77
|
# @return [Boolean] when true, {#emit_verbose_monitor_event} forwards
|
|
74
78
|
# per-message traces (:message_sent / :message_received) to the
|
|
75
79
|
# monitor queue. Set by {Socket#monitor} via its +verbose:+ kwarg.
|
|
@@ -286,6 +290,15 @@ module NNQ
|
|
|
286
290
|
# collection mutates during iteration, so snapshot the values.
|
|
287
291
|
@connections.values.each(&:close!)
|
|
288
292
|
|
|
293
|
+
# Emit :closed, seal the monitor queue, and wait for the monitor
|
|
294
|
+
# fiber to drain it before cancelling tasks. Without this join,
|
|
295
|
+
# trailing :message_received events that the recv pump enqueued
|
|
296
|
+
# just before close would be lost when the barrier.stop below
|
|
297
|
+
# Async::Stops the monitor fiber mid-dequeue.
|
|
298
|
+
emit_monitor_event(:closed)
|
|
299
|
+
close_monitor_queue
|
|
300
|
+
@monitor_task&.wait
|
|
301
|
+
|
|
289
302
|
# Cascade-cancel every remaining task (reconnect loops, accept
|
|
290
303
|
# loops, supervisors) in one shot.
|
|
291
304
|
@lifecycle.barrier&.stop
|
|
@@ -295,8 +308,6 @@ module NNQ
|
|
|
295
308
|
# Unblock anyone waiting on peer_connected when the socket is
|
|
296
309
|
# closed before a peer ever arrived.
|
|
297
310
|
@lifecycle.peer_connected.resolve(nil) unless @lifecycle.peer_connected.resolved?
|
|
298
|
-
emit_monitor_event(:closed)
|
|
299
|
-
close_monitor_queue
|
|
300
311
|
end
|
|
301
312
|
|
|
302
313
|
|
|
@@ -337,7 +348,10 @@ module NNQ
|
|
|
337
348
|
@connections[conn].barrier.async(annotation: "nnq recv #{conn.endpoint}") do
|
|
338
349
|
loop do
|
|
339
350
|
body = conn.receive_message
|
|
340
|
-
|
|
351
|
+
if @verbose_monitor
|
|
352
|
+
preview = @routing.respond_to?(:preview_body) ? @routing.preview_body(body) : body
|
|
353
|
+
emit_verbose_msg_received(preview)
|
|
354
|
+
end
|
|
341
355
|
@routing.enqueue(body, conn)
|
|
342
356
|
rescue *CONNECTION_LOST, Async::Stop
|
|
343
357
|
break
|
data/lib/nnq/routing/rep.rb
CHANGED
|
@@ -70,6 +70,14 @@ module NNQ
|
|
|
70
70
|
|
|
71
71
|
return if conn.closed?
|
|
72
72
|
conn.send_message(body, header: btrace)
|
|
73
|
+
@engine.emit_verbose_msg_sent(body)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
# Strips the backtrace header for verbose trace previews.
|
|
78
|
+
def preview_body(wire)
|
|
79
|
+
_, payload = parse_backtrace(wire)
|
|
80
|
+
payload || wire
|
|
73
81
|
end
|
|
74
82
|
|
|
75
83
|
|
data/lib/nnq/routing/rep_raw.rb
CHANGED
|
@@ -36,11 +36,18 @@ module NNQ
|
|
|
36
36
|
return if to.closed?
|
|
37
37
|
return if Backtrace.too_many_hops?(header)
|
|
38
38
|
to.send_message(body, header: header)
|
|
39
|
+
@engine.emit_verbose_msg_sent(body)
|
|
39
40
|
rescue ClosedError
|
|
40
41
|
# peer went away between receive and send — drop
|
|
41
42
|
end
|
|
42
43
|
|
|
43
44
|
|
|
45
|
+
def preview_body(wire)
|
|
46
|
+
_, payload = parse_backtrace(wire)
|
|
47
|
+
payload || wire
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
|
|
44
51
|
# Called by the engine recv loop.
|
|
45
52
|
def enqueue(wire_bytes, conn)
|
|
46
53
|
header, payload = parse_backtrace(wire_bytes)
|
data/lib/nnq/routing/req.rb
CHANGED
|
@@ -56,6 +56,7 @@ module NNQ
|
|
|
56
56
|
conn = pick_peer
|
|
57
57
|
header = [id].pack("N")
|
|
58
58
|
conn.send_message(body, header: header)
|
|
59
|
+
@engine.emit_verbose_msg_sent(body)
|
|
59
60
|
promise.wait
|
|
60
61
|
ensure
|
|
61
62
|
@mutex.synchronize do
|
|
@@ -81,6 +82,12 @@ module NNQ
|
|
|
81
82
|
end
|
|
82
83
|
|
|
83
84
|
|
|
85
|
+
# Strips the 4-byte request id for verbose trace previews.
|
|
86
|
+
def preview_body(wire)
|
|
87
|
+
wire.byteslice(4..) || wire
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
|
|
84
91
|
def close
|
|
85
92
|
@mutex.synchronize do
|
|
86
93
|
@outstanding&.last&.reject(NNQ::Error.new("REQ socket closed"))
|
data/lib/nnq/routing/req_raw.rb
CHANGED
|
@@ -52,6 +52,14 @@ module NNQ
|
|
|
52
52
|
|
|
53
53
|
return if conn.closed?
|
|
54
54
|
conn.send_message(body, header: btrace)
|
|
55
|
+
@engine.emit_verbose_msg_sent(body)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
# Strips the backtrace header for verbose trace previews.
|
|
60
|
+
def preview_body(wire)
|
|
61
|
+
_, payload = parse_backtrace(wire)
|
|
62
|
+
payload || wire
|
|
55
63
|
end
|
|
56
64
|
|
|
57
65
|
|
|
@@ -29,10 +29,17 @@ module NNQ
|
|
|
29
29
|
return if to.closed?
|
|
30
30
|
return if Backtrace.too_many_hops?(header)
|
|
31
31
|
to.send_message(body, header: header)
|
|
32
|
+
@engine.emit_verbose_msg_sent(body)
|
|
32
33
|
rescue ClosedError
|
|
33
34
|
end
|
|
34
35
|
|
|
35
36
|
|
|
37
|
+
def preview_body(wire)
|
|
38
|
+
_, payload = parse_backtrace(wire)
|
|
39
|
+
payload || wire
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
|
|
36
43
|
def enqueue(wire_bytes, conn)
|
|
37
44
|
header, payload = parse_backtrace(wire_bytes)
|
|
38
45
|
return unless header
|
data/lib/nnq/routing/surveyor.rb
CHANGED
|
@@ -78,6 +78,12 @@ module NNQ
|
|
|
78
78
|
end
|
|
79
79
|
|
|
80
80
|
|
|
81
|
+
# Strips the 4-byte survey id for verbose trace previews.
|
|
82
|
+
def preview_body(wire)
|
|
83
|
+
wire.byteslice(4..) || wire
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
|
|
81
87
|
def connection_added(conn)
|
|
82
88
|
queue = Async::LimitedQueue.new(@engine.options.send_hwm)
|
|
83
89
|
@queues[conn] = queue
|
data/lib/nnq/socket.rb
CHANGED
|
@@ -126,13 +126,14 @@ module NNQ
|
|
|
126
126
|
@engine.verbose_monitor = verbose
|
|
127
127
|
|
|
128
128
|
Reactor.run do
|
|
129
|
-
@engine.spawn_task(annotation: "nnq monitor") do
|
|
129
|
+
@engine.monitor_task = @engine.spawn_task(annotation: "nnq monitor") do
|
|
130
130
|
while (event = queue.dequeue)
|
|
131
131
|
block.call(event)
|
|
132
132
|
end
|
|
133
133
|
rescue Async::Stop
|
|
134
134
|
ensure
|
|
135
135
|
@engine.monitor_queue = nil
|
|
136
|
+
@engine.monitor_task = nil
|
|
136
137
|
block.call(MonitorEvent.new(type: :monitor_stopped))
|
|
137
138
|
end
|
|
138
139
|
end
|
data/lib/nnq/version.rb
CHANGED