omq 0.5.0 → 0.5.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 +22 -0
- data/lib/omq/version.rb +1 -1
- data/lib/omq/zmtp/connection.rb +35 -9
- data/lib/omq/zmtp/reactor.rb +17 -33
- data/lib/omq/zmtp/routing/channel.rb +6 -1
- data/lib/omq/zmtp/routing/fan_out.rb +20 -8
- data/lib/omq/zmtp/routing/pair.rb +6 -1
- data/lib/omq/zmtp/routing/peer.rb +21 -5
- data/lib/omq/zmtp/routing/radio.rb +22 -10
- data/lib/omq/zmtp/routing/rep.rb +21 -6
- data/lib/omq/zmtp/routing/round_robin.rb +37 -2
- data/lib/omq/zmtp/routing/router.rb +23 -9
- data/lib/omq/zmtp/routing/server.rb +21 -5
- data/lib/omq/zmtp/routing.rb +19 -0
- data/lib/omq/zmtp/transport/inproc.rb +8 -0
- 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: 76cecd3650f9fb73d699a027570421f589452a40cf6bbf207af02afb2bc6df08
|
|
4
|
+
data.tar.gz: 0252e01bacd5278defe46ed9ab4750b3e33ca71e928beb13f1092c23a7c2ce62
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: de2508cbe4e22c6dc93bdeab4626fed0c5280cf74eaaf4c4f886f566719a3c732f5db9b766c201f7e9d6eb7bb00ee4ed2d2392eec232abe88c7847148b889fc5
|
|
7
|
+
data.tar.gz: 65e96cef70697abe90588e5e35f4563e55ef183bb0be44276c6cb62ec007f6accb4e482a08c14d89b15ec3f542d75c78bacc87c6174ca6f4e69b588ddb540730
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.1 — 2026-03-28
|
|
4
|
+
|
|
5
|
+
### Improved
|
|
6
|
+
|
|
7
|
+
- **3–4x throughput under burst load** — send pumps now batch writes
|
|
8
|
+
before flushing. `Connection#write_message` buffers without flushing;
|
|
9
|
+
`Connection#flush` triggers the syscall. Pumps drain all queued messages
|
|
10
|
+
per cycle, reducing flush count from `N_msgs × N_conns` to `N_conns`
|
|
11
|
+
per batch. PUB/SUB TCP with 10 subscribers: 2.3k → 9.2k msg/s (**4x**).
|
|
12
|
+
PUSH/PULL TCP: 24k → 83k msg/s (**3.4x**). Zero overhead under light
|
|
13
|
+
load (batch of 1 = same path as before).
|
|
14
|
+
|
|
15
|
+
- **Simplified Reactor IO thread** — replaced `Thread::Queue` + `IO.pipe`
|
|
16
|
+
wake signal with a single `Async::Queue`. `Thread::Queue#pop` is
|
|
17
|
+
fiber-scheduler-aware in Ruby 4.0, so the pipe pair was unnecessary.
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- **`router_mandatory` SocketError raised in send pump** — the error
|
|
22
|
+
killed the pump fiber instead of reaching the caller. Now checked
|
|
23
|
+
synchronously in `enqueue` before queuing.
|
|
24
|
+
|
|
3
25
|
## 0.5.0 — 2026-03-28
|
|
4
26
|
|
|
5
27
|
### Added
|
data/lib/omq/version.rb
CHANGED
data/lib/omq/zmtp/connection.rb
CHANGED
|
@@ -77,21 +77,36 @@ module OMQ
|
|
|
77
77
|
end
|
|
78
78
|
end
|
|
79
79
|
|
|
80
|
-
# Sends a multi-frame message.
|
|
80
|
+
# Sends a multi-frame message (write + flush).
|
|
81
81
|
#
|
|
82
82
|
# @param parts [Array<String>] message frames
|
|
83
83
|
# @return [void]
|
|
84
84
|
#
|
|
85
85
|
def send_message(parts)
|
|
86
86
|
@mutex.synchronize do
|
|
87
|
-
parts
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
87
|
+
write_frames(parts)
|
|
88
|
+
@io.flush
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Writes a multi-frame message to the buffer without flushing.
|
|
93
|
+
# Call {#flush} after batching writes.
|
|
94
|
+
#
|
|
95
|
+
# @param parts [Array<String>] message frames
|
|
96
|
+
# @return [void]
|
|
97
|
+
#
|
|
98
|
+
def write_message(parts)
|
|
99
|
+
@mutex.synchronize do
|
|
100
|
+
write_frames(parts)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Flushes the write buffer to the underlying IO.
|
|
105
|
+
#
|
|
106
|
+
# @return [void]
|
|
107
|
+
#
|
|
108
|
+
def flush
|
|
109
|
+
@mutex.synchronize do
|
|
95
110
|
@io.flush
|
|
96
111
|
end
|
|
97
112
|
end
|
|
@@ -213,6 +228,17 @@ module OMQ
|
|
|
213
228
|
|
|
214
229
|
private
|
|
215
230
|
|
|
231
|
+
def write_frames(parts)
|
|
232
|
+
parts.each_with_index do |part, i|
|
|
233
|
+
more = i < parts.size - 1
|
|
234
|
+
if @mechanism.encrypted?
|
|
235
|
+
@io.write(@mechanism.encrypt(part.b, more: more))
|
|
236
|
+
else
|
|
237
|
+
@io.write(Codec::Frame.new(part, more: more).to_wire)
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
|
|
216
242
|
def touch_heartbeat
|
|
217
243
|
@last_received_at = monotonic_now if @heartbeat_interval
|
|
218
244
|
end
|
data/lib/omq/zmtp/reactor.rb
CHANGED
|
@@ -12,11 +12,9 @@ module OMQ
|
|
|
12
12
|
# tasks — mirroring libzmq's IO thread architecture.
|
|
13
13
|
#
|
|
14
14
|
module Reactor
|
|
15
|
-
@work_queue =
|
|
15
|
+
@work_queue = Async::Queue.new
|
|
16
16
|
@thread = nil
|
|
17
17
|
@mutex = Mutex.new
|
|
18
|
-
@wake_r = nil
|
|
19
|
-
@wake_w = nil
|
|
20
18
|
|
|
21
19
|
class << self
|
|
22
20
|
# Spawns a pump task (recv loop, send loop, accept loop).
|
|
@@ -33,7 +31,6 @@ module OMQ
|
|
|
33
31
|
handle = PumpHandle.new
|
|
34
32
|
ensure_started
|
|
35
33
|
@work_queue.push([:spawn, block, handle])
|
|
36
|
-
@wake_w.write_nonblock(".") rescue nil
|
|
37
34
|
handle
|
|
38
35
|
end
|
|
39
36
|
end
|
|
@@ -52,7 +49,6 @@ module OMQ
|
|
|
52
49
|
result_queue = Thread::Queue.new
|
|
53
50
|
ensure_started
|
|
54
51
|
@work_queue.push([:run, block, result_queue])
|
|
55
|
-
@wake_w.write_nonblock(".") rescue nil
|
|
56
52
|
status, value = result_queue.pop
|
|
57
53
|
raise value if status == :error
|
|
58
54
|
value
|
|
@@ -66,9 +62,8 @@ module OMQ
|
|
|
66
62
|
def ensure_started
|
|
67
63
|
@mutex.synchronize do
|
|
68
64
|
return if @thread&.alive?
|
|
69
|
-
@wake_r, @wake_w = IO.pipe
|
|
70
65
|
ready = Thread::Queue.new
|
|
71
|
-
@thread = Thread.new { run_reactor(ready
|
|
66
|
+
@thread = Thread.new { run_reactor(ready) }
|
|
72
67
|
@thread.name = "omq-io"
|
|
73
68
|
ready.pop
|
|
74
69
|
end
|
|
@@ -80,42 +75,31 @@ module OMQ
|
|
|
80
75
|
#
|
|
81
76
|
def stop!
|
|
82
77
|
@work_queue.push([:stop])
|
|
83
|
-
@wake_w&.write_nonblock(".") rescue nil
|
|
84
78
|
@thread&.join(2)
|
|
85
79
|
@thread = nil
|
|
86
|
-
@wake_r&.close rescue nil
|
|
87
|
-
@wake_w&.close rescue nil
|
|
88
|
-
@wake_r = nil
|
|
89
|
-
@wake_w = nil
|
|
90
80
|
end
|
|
91
81
|
|
|
92
82
|
private
|
|
93
83
|
|
|
94
|
-
def run_reactor(ready
|
|
84
|
+
def run_reactor(ready)
|
|
95
85
|
Async do |task|
|
|
96
86
|
ready.push(true)
|
|
97
87
|
loop do
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
_, block, result_queue = item
|
|
111
|
-
task.async do
|
|
112
|
-
result_queue.push([:ok, block.call])
|
|
113
|
-
rescue => e
|
|
114
|
-
result_queue.push([:error, e])
|
|
115
|
-
end
|
|
116
|
-
when :stop
|
|
117
|
-
return
|
|
88
|
+
item = @work_queue.dequeue
|
|
89
|
+
case item[0]
|
|
90
|
+
when :spawn
|
|
91
|
+
_, block, handle = item
|
|
92
|
+
async_task = task.async(transient: true, &block)
|
|
93
|
+
handle.task = async_task
|
|
94
|
+
when :run
|
|
95
|
+
_, block, result_queue = item
|
|
96
|
+
task.async do
|
|
97
|
+
result_queue.push([:ok, block.call])
|
|
98
|
+
rescue => e
|
|
99
|
+
result_queue.push([:error, e])
|
|
118
100
|
end
|
|
101
|
+
when :stop
|
|
102
|
+
return
|
|
119
103
|
end
|
|
120
104
|
end
|
|
121
105
|
end
|
|
@@ -58,7 +58,12 @@ module OMQ
|
|
|
58
58
|
|
|
59
59
|
def start_send_pump(conn)
|
|
60
60
|
@send_pump = Reactor.spawn_pump do
|
|
61
|
-
loop
|
|
61
|
+
loop do
|
|
62
|
+
batch = [@send_queue.dequeue]
|
|
63
|
+
Routing.drain_send_queue(@send_queue, batch)
|
|
64
|
+
batch.each { |parts| conn.write_message(parts) }
|
|
65
|
+
conn.flush
|
|
66
|
+
end
|
|
62
67
|
rescue *ZMTP::CONNECTION_LOST
|
|
63
68
|
@engine.connection_lost(conn)
|
|
64
69
|
end
|
|
@@ -54,16 +54,28 @@ module OMQ
|
|
|
54
54
|
@send_pump_started = true
|
|
55
55
|
@tasks << Reactor.spawn_pump do
|
|
56
56
|
loop do
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
57
|
+
batch = [@send_queue.dequeue]
|
|
58
|
+
Routing.drain_send_queue(@send_queue, batch)
|
|
59
|
+
|
|
60
|
+
written = Set.new
|
|
61
|
+
batch.each do |parts|
|
|
62
|
+
topic = parts.first || "".b
|
|
63
|
+
@connections.each do |conn|
|
|
64
|
+
next unless subscribed?(conn, topic)
|
|
65
|
+
begin
|
|
66
|
+
conn.write_message(parts)
|
|
67
|
+
written << conn
|
|
68
|
+
rescue *ZMTP::CONNECTION_LOST
|
|
69
|
+
# connection dead — will be cleaned up
|
|
70
|
+
end
|
|
65
71
|
end
|
|
66
72
|
end
|
|
73
|
+
|
|
74
|
+
written.each do |conn|
|
|
75
|
+
conn.flush
|
|
76
|
+
rescue *ZMTP::CONNECTION_LOST
|
|
77
|
+
# connection dead — will be cleaned up
|
|
78
|
+
end
|
|
67
79
|
end
|
|
68
80
|
end
|
|
69
81
|
end
|
|
@@ -61,7 +61,12 @@ module OMQ
|
|
|
61
61
|
|
|
62
62
|
def start_send_pump(conn)
|
|
63
63
|
@send_pump = Reactor.spawn_pump do
|
|
64
|
-
loop
|
|
64
|
+
loop do
|
|
65
|
+
batch = [@send_queue.dequeue]
|
|
66
|
+
Routing.drain_send_queue(@send_queue, batch)
|
|
67
|
+
batch.each { |parts| conn.write_message(parts) }
|
|
68
|
+
conn.flush
|
|
69
|
+
end
|
|
65
70
|
rescue *ZMTP::CONNECTION_LOST
|
|
66
71
|
@engine.connection_lost(conn)
|
|
67
72
|
end
|
|
@@ -63,11 +63,27 @@ module OMQ
|
|
|
63
63
|
@send_pump_started = true
|
|
64
64
|
@tasks << Reactor.spawn_pump do
|
|
65
65
|
loop do
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
66
|
+
batch = [@send_queue.dequeue]
|
|
67
|
+
Routing.drain_send_queue(@send_queue, batch)
|
|
68
|
+
|
|
69
|
+
written = Set.new
|
|
70
|
+
batch.each do |parts|
|
|
71
|
+
routing_id = parts.first
|
|
72
|
+
conn = @connections_by_routing_id[routing_id]
|
|
73
|
+
next unless conn # silently drop if peer gone
|
|
74
|
+
begin
|
|
75
|
+
conn.write_message(parts[1..])
|
|
76
|
+
written << conn
|
|
77
|
+
rescue *ZMTP::CONNECTION_LOST
|
|
78
|
+
# will be cleaned up
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
written.each do |conn|
|
|
83
|
+
conn.flush
|
|
84
|
+
rescue *ZMTP::CONNECTION_LOST
|
|
85
|
+
# will be cleaned up
|
|
86
|
+
end
|
|
71
87
|
end
|
|
72
88
|
end
|
|
73
89
|
end
|
|
@@ -69,18 +69,30 @@ module OMQ
|
|
|
69
69
|
@send_pump_started = true
|
|
70
70
|
@tasks << Reactor.spawn_pump do
|
|
71
71
|
loop do
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
72
|
+
batch = [@send_queue.dequeue]
|
|
73
|
+
Routing.drain_send_queue(@send_queue, batch)
|
|
74
|
+
|
|
75
|
+
written = Set.new
|
|
76
|
+
batch.each do |parts|
|
|
77
|
+
group = parts[0]
|
|
78
|
+
body = parts[1] || "".b
|
|
79
|
+
@connections.each do |conn|
|
|
80
|
+
next unless @groups[conn]&.include?(group)
|
|
81
|
+
begin
|
|
82
|
+
# Wire format: group frame (MORE) + body frame
|
|
83
|
+
conn.write_message([group, body])
|
|
84
|
+
written << conn
|
|
85
|
+
rescue *ZMTP::CONNECTION_LOST
|
|
86
|
+
# connection dead — will be cleaned up
|
|
87
|
+
end
|
|
82
88
|
end
|
|
83
89
|
end
|
|
90
|
+
|
|
91
|
+
written.each do |conn|
|
|
92
|
+
conn.flush
|
|
93
|
+
rescue *ZMTP::CONNECTION_LOST
|
|
94
|
+
# connection dead — will be cleaned up
|
|
95
|
+
end
|
|
84
96
|
end
|
|
85
97
|
end
|
|
86
98
|
end
|
data/lib/omq/zmtp/routing/rep.rb
CHANGED
|
@@ -68,13 +68,28 @@ module OMQ
|
|
|
68
68
|
@send_pump_started = true
|
|
69
69
|
@tasks << Reactor.spawn_pump do
|
|
70
70
|
loop do
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
batch = [@send_queue.dequeue]
|
|
72
|
+
Routing.drain_send_queue(@send_queue, batch)
|
|
73
|
+
|
|
74
|
+
written = Set.new
|
|
75
|
+
batch.each do |parts|
|
|
76
|
+
reply_info = @pending_replies.shift
|
|
77
|
+
next unless reply_info
|
|
78
|
+
conn = reply_info[:conn]
|
|
79
|
+
begin
|
|
80
|
+
conn.write_message([*reply_info[:envelope], "".b, *parts])
|
|
81
|
+
written << conn
|
|
82
|
+
rescue *ZMTP::CONNECTION_LOST
|
|
83
|
+
# connection lost mid-write
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
written.each do |conn|
|
|
88
|
+
conn.flush
|
|
89
|
+
rescue *ZMTP::CONNECTION_LOST
|
|
90
|
+
# connection lost mid-flush
|
|
91
|
+
end
|
|
75
92
|
end
|
|
76
|
-
rescue *ZMTP::CONNECTION_LOST
|
|
77
|
-
# connection lost mid-write
|
|
78
93
|
end
|
|
79
94
|
end
|
|
80
95
|
end
|
|
@@ -55,8 +55,14 @@ module OMQ
|
|
|
55
55
|
@send_pump_started = true
|
|
56
56
|
@tasks << Reactor.spawn_pump do
|
|
57
57
|
loop do
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
batch = [@send_queue.dequeue]
|
|
59
|
+
Routing.drain_send_queue(@send_queue, batch)
|
|
60
|
+
|
|
61
|
+
if batch.size == 1
|
|
62
|
+
send_with_retry(batch[0])
|
|
63
|
+
else
|
|
64
|
+
send_batch(batch)
|
|
65
|
+
end
|
|
60
66
|
end
|
|
61
67
|
end
|
|
62
68
|
end
|
|
@@ -68,6 +74,35 @@ module OMQ
|
|
|
68
74
|
@engine.connection_lost(conn)
|
|
69
75
|
retry
|
|
70
76
|
end
|
|
77
|
+
|
|
78
|
+
def send_batch(batch)
|
|
79
|
+
written = Set.new
|
|
80
|
+
batch.each_with_index do |parts, i|
|
|
81
|
+
conn = next_connection
|
|
82
|
+
begin
|
|
83
|
+
conn.write_message(transform_send(parts))
|
|
84
|
+
written << conn
|
|
85
|
+
rescue *ZMTP::CONNECTION_LOST
|
|
86
|
+
@engine.connection_lost(conn)
|
|
87
|
+
# Flush what we've written so far
|
|
88
|
+
written.each do |c|
|
|
89
|
+
c.flush
|
|
90
|
+
rescue *ZMTP::CONNECTION_LOST
|
|
91
|
+
# will be cleaned up
|
|
92
|
+
end
|
|
93
|
+
written.clear
|
|
94
|
+
# Fall back to send_with_retry for this and remaining
|
|
95
|
+
send_with_retry(parts)
|
|
96
|
+
batch[(i + 1)..].each { |p| send_with_retry(p) }
|
|
97
|
+
return
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
written.each do |conn|
|
|
101
|
+
conn.flush
|
|
102
|
+
rescue *ZMTP::CONNECTION_LOST
|
|
103
|
+
# will be cleaned up
|
|
104
|
+
end
|
|
105
|
+
end
|
|
71
106
|
end
|
|
72
107
|
end
|
|
73
108
|
end
|
|
@@ -52,6 +52,12 @@ module OMQ
|
|
|
52
52
|
# @param parts [Array<String>]
|
|
53
53
|
#
|
|
54
54
|
def enqueue(parts)
|
|
55
|
+
if @engine.options.router_mandatory?
|
|
56
|
+
identity = parts.first
|
|
57
|
+
unless @connections_by_identity[identity]
|
|
58
|
+
raise SocketError, "no route to identity #{identity.inspect}"
|
|
59
|
+
end
|
|
60
|
+
end
|
|
55
61
|
@send_queue.enqueue(parts)
|
|
56
62
|
end
|
|
57
63
|
|
|
@@ -66,19 +72,27 @@ module OMQ
|
|
|
66
72
|
@send_pump_started = true
|
|
67
73
|
@tasks << Reactor.spawn_pump do
|
|
68
74
|
loop do
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
conn = @connections_by_identity[identity]
|
|
75
|
+
batch = [@send_queue.dequeue]
|
|
76
|
+
Routing.drain_send_queue(@send_queue, batch)
|
|
72
77
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
78
|
+
written = Set.new
|
|
79
|
+
batch.each do |parts|
|
|
80
|
+
identity = parts.first
|
|
81
|
+
conn = @connections_by_identity[identity]
|
|
82
|
+
next unless conn # silently drop (peer may have disconnected)
|
|
83
|
+
begin
|
|
84
|
+
conn.write_message(parts[1..])
|
|
85
|
+
written << conn
|
|
86
|
+
rescue *ZMTP::CONNECTION_LOST
|
|
87
|
+
# will be cleaned up
|
|
76
88
|
end
|
|
77
|
-
next # silently drop
|
|
78
89
|
end
|
|
79
90
|
|
|
80
|
-
|
|
81
|
-
|
|
91
|
+
written.each do |conn|
|
|
92
|
+
conn.flush
|
|
93
|
+
rescue *ZMTP::CONNECTION_LOST
|
|
94
|
+
# will be cleaned up
|
|
95
|
+
end
|
|
82
96
|
end
|
|
83
97
|
end
|
|
84
98
|
end
|
|
@@ -63,11 +63,27 @@ module OMQ
|
|
|
63
63
|
@send_pump_started = true
|
|
64
64
|
@tasks << Reactor.spawn_pump do
|
|
65
65
|
loop do
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
66
|
+
batch = [@send_queue.dequeue]
|
|
67
|
+
Routing.drain_send_queue(@send_queue, batch)
|
|
68
|
+
|
|
69
|
+
written = Set.new
|
|
70
|
+
batch.each do |parts|
|
|
71
|
+
routing_id = parts.first
|
|
72
|
+
conn = @connections_by_routing_id[routing_id]
|
|
73
|
+
next unless conn # silently drop if peer gone
|
|
74
|
+
begin
|
|
75
|
+
conn.write_message(parts[1..])
|
|
76
|
+
written << conn
|
|
77
|
+
rescue *ZMTP::CONNECTION_LOST
|
|
78
|
+
# will be cleaned up
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
written.each do |conn|
|
|
83
|
+
conn.flush
|
|
84
|
+
rescue *ZMTP::CONNECTION_LOST
|
|
85
|
+
# will be cleaned up
|
|
86
|
+
end
|
|
71
87
|
end
|
|
72
88
|
end
|
|
73
89
|
end
|
data/lib/omq/zmtp/routing.rb
CHANGED
|
@@ -12,6 +12,25 @@ module OMQ
|
|
|
12
12
|
# the socket's send/recv queues.
|
|
13
13
|
#
|
|
14
14
|
module Routing
|
|
15
|
+
# Maximum messages to drain from the send queue per flush cycle.
|
|
16
|
+
MAX_SEND_BATCH = 64
|
|
17
|
+
|
|
18
|
+
# Drains up to +max+ additional messages from +queue+ into +batch+
|
|
19
|
+
# without blocking. Call after the initial blocking dequeue.
|
|
20
|
+
#
|
|
21
|
+
# @param queue [Async::LimitedQueue]
|
|
22
|
+
# @param batch [Array]
|
|
23
|
+
# @param max [Integer]
|
|
24
|
+
# @return [void]
|
|
25
|
+
#
|
|
26
|
+
def self.drain_send_queue(queue, batch, max = MAX_SEND_BATCH)
|
|
27
|
+
while batch.size < max
|
|
28
|
+
msg = queue.dequeue(timeout: 0)
|
|
29
|
+
break unless msg
|
|
30
|
+
batch << msg
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
15
34
|
# Returns the routing strategy class for a socket type.
|
|
16
35
|
#
|
|
17
36
|
# @param socket_type [Symbol] e.g. :PAIR, :REQ
|
|
@@ -262,6 +262,14 @@ module OMQ
|
|
|
262
262
|
end
|
|
263
263
|
end
|
|
264
264
|
|
|
265
|
+
alias write_message send_message
|
|
266
|
+
|
|
267
|
+
# No-op — inproc has no IO buffer to flush.
|
|
268
|
+
#
|
|
269
|
+
# @return [void]
|
|
270
|
+
#
|
|
271
|
+
def flush = nil
|
|
272
|
+
|
|
265
273
|
# Receives a multi-frame message.
|
|
266
274
|
#
|
|
267
275
|
# @return [Array<String>]
|