omq 0.22.0 → 0.22.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 +24 -0
- data/lib/omq/engine/heartbeat.rb +1 -1
- data/lib/omq/routing/conn_send_pump.rb +8 -3
- data/lib/omq/routing/fan_out.rb +9 -4
- data/lib/omq/routing/pair.rb +4 -2
- data/lib/omq/routing/rep.rb +8 -4
- data/lib/omq/routing/req.rb +1 -1
- data/lib/omq/routing/round_robin.rb +6 -3
- data/lib/omq/routing.rb +5 -2
- 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: f58b9e0c8c49bcdfb8dd80ec5eda6a6b6e5b09f04a2a7851001449449ba448fd
|
|
4
|
+
data.tar.gz: 0f6cbd451adc8b1d1cde0771d6535c5959f09e4b3f0442164b0544964755795e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d7d13f97eeacf998f1e0137bdbc5dd4a471195ff628fd7da97720a019e30c2a9c200fab761c38943bbbada056bf81880e6ca2dd87d3936f150f0fa22566cebe5
|
|
7
|
+
data.tar.gz: f97931ecb4893ecd0155c37ea18793c9414bd57de6918496ef7af18bad714720aa2e146531788956265d6f85bc3e18f6dd403f71df8683913d322c94a6dd1bdb
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.22.1 — 2026-04-16
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- **Reuse batch arrays in send pumps.** All send pumps (RoundRobin,
|
|
8
|
+
Pair, ConnSendPump, FanOut, FanOut-conflate) now pre-allocate a
|
|
9
|
+
single batch array and clear it between cycles instead of
|
|
10
|
+
allocating a fresh `[msg]` per dequeue.
|
|
11
|
+
|
|
12
|
+
- **`Routing.dequeue_batch`** consolidates the blocking-dequeue +
|
|
13
|
+
non-blocking-sweep pattern that was duplicated across four call
|
|
14
|
+
sites into one method. `dequeue_batch_capped` does the same for
|
|
15
|
+
the byte/message-capped RoundRobin variant.
|
|
16
|
+
|
|
17
|
+
- **REP envelope stored as `[conn, envelope]`** instead of a Hash,
|
|
18
|
+
and reply assembly uses `<<` + `concat` instead of double splat.
|
|
19
|
+
|
|
20
|
+
- **Heartbeat drops redundant `context: "".b`** — the default is
|
|
21
|
+
now `EMPTY_BINARY` in protocol-zmtp.
|
|
22
|
+
|
|
23
|
+
- **Bench harness accepts `OMQ_BENCH_SIZES`, `OMQ_BENCH_TRANSPORTS`,
|
|
24
|
+
and `OMQ_BENCH_PEERS`** env vars to scope runs without editing
|
|
25
|
+
code.
|
|
26
|
+
|
|
3
27
|
## 0.22.0 — 2026-04-15
|
|
4
28
|
|
|
5
29
|
### Fixed
|
data/lib/omq/engine/heartbeat.rb
CHANGED
|
@@ -24,7 +24,7 @@ module OMQ
|
|
|
24
24
|
tasks << parent.async(transient: true, annotation: "heartbeat") do
|
|
25
25
|
loop do
|
|
26
26
|
sleep interval
|
|
27
|
-
conn.send_command(Protocol::ZMTP::Codec::Command.ping(ttl: ttl
|
|
27
|
+
conn.send_command(Protocol::ZMTP::Codec::Command.ping(ttl: ttl))
|
|
28
28
|
if conn.heartbeat_expired?(timeout)
|
|
29
29
|
conn.close
|
|
30
30
|
break
|
|
@@ -18,9 +18,10 @@ module OMQ
|
|
|
18
18
|
#
|
|
19
19
|
def self.start(engine, conn, q, tasks)
|
|
20
20
|
task = engine.spawn_conn_pump_task(conn, annotation: "send pump") do
|
|
21
|
+
batch = []
|
|
22
|
+
|
|
21
23
|
loop do
|
|
22
|
-
batch
|
|
23
|
-
Routing.drain_send_queue(q, batch)
|
|
24
|
+
Routing.dequeue_batch(q, batch)
|
|
24
25
|
|
|
25
26
|
if batch.size == 1
|
|
26
27
|
conn.write_message batch.first
|
|
@@ -30,7 +31,11 @@ module OMQ
|
|
|
30
31
|
|
|
31
32
|
conn.flush
|
|
32
33
|
|
|
33
|
-
batch.each
|
|
34
|
+
batch.each do |parts|
|
|
35
|
+
engine.emit_verbose_msg_sent(conn, parts)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
batch.clear
|
|
34
39
|
end
|
|
35
40
|
end
|
|
36
41
|
|
data/lib/omq/routing/fan_out.rb
CHANGED
|
@@ -181,14 +181,16 @@ module OMQ
|
|
|
181
181
|
#
|
|
182
182
|
def start_conn_send_pump_normal(conn, q, use_wire)
|
|
183
183
|
@engine.spawn_conn_pump_task(conn, annotation: "send pump") do
|
|
184
|
+
batch = []
|
|
185
|
+
|
|
184
186
|
loop do
|
|
185
|
-
batch
|
|
186
|
-
Routing.drain_send_queue(q, batch)
|
|
187
|
+
Routing.dequeue_batch(q, batch)
|
|
187
188
|
|
|
188
189
|
if write_matching_batch(conn, batch, use_wire)
|
|
189
190
|
conn.flush
|
|
190
191
|
batch.each { |parts| @engine.emit_verbose_msg_sent(conn, parts) }
|
|
191
192
|
end
|
|
193
|
+
batch.clear
|
|
192
194
|
end
|
|
193
195
|
end
|
|
194
196
|
end
|
|
@@ -227,14 +229,17 @@ module OMQ
|
|
|
227
229
|
#
|
|
228
230
|
def start_conn_send_pump_conflate(conn, q)
|
|
229
231
|
@engine.spawn_conn_pump_task(conn, annotation: "send pump") do
|
|
232
|
+
batch = []
|
|
233
|
+
|
|
230
234
|
loop do
|
|
231
|
-
batch
|
|
232
|
-
Routing.drain_send_queue(q, batch)
|
|
235
|
+
Routing.dequeue_batch(q, batch)
|
|
233
236
|
|
|
234
237
|
# Keep only the latest message that matches the subscription.
|
|
235
238
|
latest = batch.reverse.find do |parts|
|
|
236
239
|
subscribed?(conn, parts.first || EMPTY_BINARY)
|
|
237
240
|
end
|
|
241
|
+
|
|
242
|
+
batch.clear
|
|
238
243
|
next unless latest
|
|
239
244
|
|
|
240
245
|
conn.write_message(latest)
|
data/lib/omq/routing/pair.rb
CHANGED
|
@@ -106,9 +106,10 @@ module OMQ
|
|
|
106
106
|
|
|
107
107
|
def start_send_pump(conn)
|
|
108
108
|
@send_pump = @engine.spawn_conn_pump_task(conn, annotation: "send pump") do
|
|
109
|
+
batch = []
|
|
110
|
+
|
|
109
111
|
loop do
|
|
110
|
-
|
|
111
|
-
Routing.drain_send_queue(@send_queue, batch)
|
|
112
|
+
Routing.dequeue_batch(@send_queue, batch)
|
|
112
113
|
|
|
113
114
|
if batch.size == 1
|
|
114
115
|
conn.write_message(batch.first)
|
|
@@ -120,6 +121,7 @@ module OMQ
|
|
|
120
121
|
batch.each do |parts|
|
|
121
122
|
@engine.emit_verbose_msg_sent(conn, parts)
|
|
122
123
|
end
|
|
124
|
+
batch.clear
|
|
123
125
|
end
|
|
124
126
|
end
|
|
125
127
|
|
data/lib/omq/routing/rep.rb
CHANGED
|
@@ -55,7 +55,7 @@ module OMQ
|
|
|
55
55
|
envelope = msg[0, delimiter]
|
|
56
56
|
body = msg[(delimiter + 1)..] || []
|
|
57
57
|
|
|
58
|
-
@pending_replies <<
|
|
58
|
+
@pending_replies << [connection, envelope]
|
|
59
59
|
body
|
|
60
60
|
end
|
|
61
61
|
@tasks << task if task
|
|
@@ -69,7 +69,7 @@ module OMQ
|
|
|
69
69
|
# @param connection [Connection]
|
|
70
70
|
#
|
|
71
71
|
def connection_removed(connection)
|
|
72
|
-
@pending_replies.reject! { |r| r[
|
|
72
|
+
@pending_replies.reject! { |r| r[0] == connection }
|
|
73
73
|
@conn_queues.delete(connection)
|
|
74
74
|
@conn_send_tasks.delete(connection)&.stop
|
|
75
75
|
end
|
|
@@ -83,8 +83,12 @@ module OMQ
|
|
|
83
83
|
def enqueue(parts)
|
|
84
84
|
reply_info = @pending_replies.shift
|
|
85
85
|
return unless reply_info
|
|
86
|
-
|
|
87
|
-
|
|
86
|
+
|
|
87
|
+
conn, envelope = reply_info
|
|
88
|
+
msg = envelope
|
|
89
|
+
msg << EMPTY_FRAME
|
|
90
|
+
msg.concat(parts)
|
|
91
|
+
@conn_queues[conn]&.enqueue(msg)
|
|
88
92
|
end
|
|
89
93
|
|
|
90
94
|
|
data/lib/omq/routing/req.rb
CHANGED
|
@@ -133,9 +133,10 @@ module OMQ
|
|
|
133
133
|
#
|
|
134
134
|
def start_conn_send_pump(conn)
|
|
135
135
|
task = @engine.spawn_conn_pump_task(conn, annotation: "send pump") do
|
|
136
|
+
batch = []
|
|
137
|
+
|
|
136
138
|
loop do
|
|
137
|
-
batch
|
|
138
|
-
drain_send_queue_capped(batch)
|
|
139
|
+
dequeue_batch_capped(batch)
|
|
139
140
|
@in_flight += batch.size
|
|
140
141
|
|
|
141
142
|
begin
|
|
@@ -147,6 +148,7 @@ module OMQ
|
|
|
147
148
|
batch.each do |parts|
|
|
148
149
|
@engine.emit_verbose_msg_sent(conn, parts)
|
|
149
150
|
end
|
|
151
|
+
batch.clear
|
|
150
152
|
|
|
151
153
|
Async::Task.current.yield
|
|
152
154
|
end
|
|
@@ -157,7 +159,8 @@ module OMQ
|
|
|
157
159
|
end
|
|
158
160
|
|
|
159
161
|
|
|
160
|
-
def
|
|
162
|
+
def dequeue_batch_capped(batch = [])
|
|
163
|
+
batch << @send_queue.dequeue
|
|
161
164
|
bytes = batch_bytes(batch.first)
|
|
162
165
|
|
|
163
166
|
while batch.size < BATCH_MSG_CAP && bytes < BATCH_BYTE_CAP
|
data/lib/omq/routing.rb
CHANGED
|
@@ -57,7 +57,8 @@ module OMQ
|
|
|
57
57
|
|
|
58
58
|
|
|
59
59
|
# Drains all available messages from +queue+ into +batch+ without
|
|
60
|
-
#
|
|
60
|
+
# Blocks for the first message, then sweeps all immediately
|
|
61
|
+
# available messages into +batch+ without blocking.
|
|
61
62
|
#
|
|
62
63
|
# No cap is needed: IO::Stream auto-flushes at 64 KB, so the
|
|
63
64
|
# write buffer hits the wire naturally under sustained load.
|
|
@@ -67,7 +68,9 @@ module OMQ
|
|
|
67
68
|
# @param batch [Array]
|
|
68
69
|
# @return [void]
|
|
69
70
|
#
|
|
70
|
-
def self.
|
|
71
|
+
def self.dequeue_batch(queue, batch = [])
|
|
72
|
+
batch << queue.dequeue
|
|
73
|
+
|
|
71
74
|
loop do
|
|
72
75
|
msg = queue.dequeue(timeout: 0) or break
|
|
73
76
|
batch << msg
|
data/lib/omq/version.rb
CHANGED