omq 0.19.0 → 0.19.3
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 +61 -0
- data/lib/omq/engine/connection_lifecycle.rb +15 -6
- data/lib/omq/engine/recv_pump.rb +16 -8
- data/lib/omq/engine.rb +84 -23
- data/lib/omq/routing/conn_send_pump.rb +1 -0
- data/lib/omq/routing/dealer.rb +6 -5
- data/lib/omq/routing/fair_queue.rb +5 -2
- data/lib/omq/routing/fair_recv.rb +28 -2
- data/lib/omq/routing/fan_out.rb +14 -1
- data/lib/omq/routing/pair.rb +15 -5
- data/lib/omq/routing/pub.rb +12 -1
- data/lib/omq/routing/pull.rb +4 -0
- data/lib/omq/routing/push.rb +14 -1
- data/lib/omq/routing/rep.rb +7 -5
- data/lib/omq/routing/req.rb +5 -5
- data/lib/omq/routing/round_robin.rb +29 -7
- data/lib/omq/routing/router.rb +7 -4
- data/lib/omq/routing/sub.rb +16 -2
- data/lib/omq/routing/xpub.rb +18 -2
- data/lib/omq/routing/xsub.rb +25 -3
- data/lib/omq/routing.rb +1 -0
- data/lib/omq/single_frame.rb +1 -0
- data/lib/omq/socket.rb +45 -28
- data/lib/omq/transport/inproc/direct_pipe.rb +6 -2
- data/lib/omq/transport/tcp.rb +1 -0
- data/lib/omq/version.rb +1 -1
- data/lib/omq/writable.rb +28 -19
- metadata +1 -1
data/lib/omq/routing/pull.rb
CHANGED
|
@@ -6,6 +6,8 @@ module OMQ
|
|
|
6
6
|
#
|
|
7
7
|
class Pull
|
|
8
8
|
include FairRecv
|
|
9
|
+
|
|
10
|
+
|
|
9
11
|
# @param engine [Engine]
|
|
10
12
|
#
|
|
11
13
|
def initialize(engine)
|
|
@@ -19,6 +21,7 @@ module OMQ
|
|
|
19
21
|
#
|
|
20
22
|
attr_reader :recv_queue
|
|
21
23
|
|
|
24
|
+
|
|
22
25
|
# @param connection [Connection]
|
|
23
26
|
#
|
|
24
27
|
def connection_added(connection)
|
|
@@ -49,6 +52,7 @@ module OMQ
|
|
|
49
52
|
@tasks.each(&:stop)
|
|
50
53
|
@tasks.clear
|
|
51
54
|
end
|
|
55
|
+
|
|
52
56
|
end
|
|
53
57
|
end
|
|
54
58
|
end
|
data/lib/omq/routing/push.rb
CHANGED
|
@@ -7,6 +7,7 @@ module OMQ
|
|
|
7
7
|
class Push
|
|
8
8
|
include RoundRobin
|
|
9
9
|
|
|
10
|
+
|
|
10
11
|
# @param engine [Engine]
|
|
11
12
|
#
|
|
12
13
|
def initialize(engine)
|
|
@@ -16,13 +17,23 @@ module OMQ
|
|
|
16
17
|
end
|
|
17
18
|
|
|
18
19
|
|
|
19
|
-
# PUSH is write-only.
|
|
20
|
+
# PUSH is write-only. Engine-facing recv contract: dequeue raises,
|
|
21
|
+
# unblock is a no-op (fatal-error propagation still calls it).
|
|
20
22
|
#
|
|
21
23
|
def recv_queue
|
|
22
24
|
raise "PUSH sockets cannot receive"
|
|
23
25
|
end
|
|
24
26
|
|
|
25
27
|
|
|
28
|
+
def dequeue_recv
|
|
29
|
+
raise "PUSH sockets cannot receive"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def unblock_recv
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
|
|
26
37
|
# @param connection [Connection]
|
|
27
38
|
#
|
|
28
39
|
def connection_added(connection)
|
|
@@ -53,6 +64,7 @@ module OMQ
|
|
|
53
64
|
@tasks.clear
|
|
54
65
|
end
|
|
55
66
|
|
|
67
|
+
|
|
56
68
|
private
|
|
57
69
|
|
|
58
70
|
|
|
@@ -66,6 +78,7 @@ module OMQ
|
|
|
66
78
|
conn.receive_message # blocks until peer disconnects; then exits
|
|
67
79
|
end
|
|
68
80
|
end
|
|
81
|
+
|
|
69
82
|
end
|
|
70
83
|
end
|
|
71
84
|
end
|
data/lib/omq/routing/rep.rb
CHANGED
|
@@ -14,6 +14,11 @@ module OMQ
|
|
|
14
14
|
EMPTY_FRAME = "".b.freeze
|
|
15
15
|
|
|
16
16
|
|
|
17
|
+
# @return [FairQueue]
|
|
18
|
+
#
|
|
19
|
+
attr_reader :recv_queue
|
|
20
|
+
|
|
21
|
+
|
|
17
22
|
# @param engine [Engine]
|
|
18
23
|
#
|
|
19
24
|
def initialize(engine)
|
|
@@ -26,17 +31,14 @@ module OMQ
|
|
|
26
31
|
end
|
|
27
32
|
|
|
28
33
|
|
|
29
|
-
# @return [FairQueue]
|
|
30
|
-
#
|
|
31
|
-
attr_reader :recv_queue
|
|
32
|
-
|
|
33
34
|
# @param connection [Connection]
|
|
34
35
|
#
|
|
35
36
|
def connection_added(connection)
|
|
36
37
|
add_fair_recv_connection(connection) do |msg|
|
|
37
|
-
delimiter = msg.index
|
|
38
|
+
delimiter = msg.index { |p| p.empty? } || msg.size
|
|
38
39
|
envelope = msg[0, delimiter]
|
|
39
40
|
body = msg[(delimiter + 1)..] || []
|
|
41
|
+
|
|
40
42
|
@pending_replies << { conn: connection, envelope: envelope }
|
|
41
43
|
body
|
|
42
44
|
end
|
data/lib/omq/routing/req.rb
CHANGED
|
@@ -14,6 +14,11 @@ module OMQ
|
|
|
14
14
|
EMPTY_BINARY = ::Protocol::ZMTP::Codec::EMPTY_BINARY
|
|
15
15
|
|
|
16
16
|
|
|
17
|
+
# @return [FairQueue]
|
|
18
|
+
#
|
|
19
|
+
attr_reader :recv_queue
|
|
20
|
+
|
|
21
|
+
|
|
17
22
|
# @param engine [Engine]
|
|
18
23
|
#
|
|
19
24
|
def initialize(engine)
|
|
@@ -25,11 +30,6 @@ module OMQ
|
|
|
25
30
|
end
|
|
26
31
|
|
|
27
32
|
|
|
28
|
-
# @return [FairQueue]
|
|
29
|
-
#
|
|
30
|
-
attr_reader :recv_queue
|
|
31
|
-
|
|
32
|
-
|
|
33
33
|
# @param connection [Connection]
|
|
34
34
|
#
|
|
35
35
|
def connection_added(connection)
|
|
@@ -19,6 +19,9 @@ module OMQ
|
|
|
19
19
|
# their #initialize.
|
|
20
20
|
#
|
|
21
21
|
module RoundRobin
|
|
22
|
+
BATCH_MSG_CAP = 256
|
|
23
|
+
BATCH_BYTE_CAP = 512 * 1024
|
|
24
|
+
|
|
22
25
|
# @return [Boolean] true when the shared send queue is empty
|
|
23
26
|
# and no pump fiber is mid-write with a dequeued batch.
|
|
24
27
|
#
|
|
@@ -26,8 +29,10 @@ module OMQ
|
|
|
26
29
|
@send_queue.empty? && @in_flight == 0
|
|
27
30
|
end
|
|
28
31
|
|
|
32
|
+
|
|
29
33
|
private
|
|
30
34
|
|
|
35
|
+
|
|
31
36
|
# Initializes the shared send queue for the including class.
|
|
32
37
|
#
|
|
33
38
|
# @param engine [Engine]
|
|
@@ -83,6 +88,7 @@ module OMQ
|
|
|
83
88
|
#
|
|
84
89
|
def enqueue_round_robin(parts)
|
|
85
90
|
pipe = @direct_pipe
|
|
91
|
+
|
|
86
92
|
if pipe&.direct_recv_queue
|
|
87
93
|
pipe.send_message(transform_send(parts))
|
|
88
94
|
else
|
|
@@ -97,7 +103,9 @@ module OMQ
|
|
|
97
103
|
# @param parts [Array<String>]
|
|
98
104
|
# @return [Array<String>]
|
|
99
105
|
#
|
|
100
|
-
def transform_send(parts)
|
|
106
|
+
def transform_send(parts)
|
|
107
|
+
parts
|
|
108
|
+
end
|
|
101
109
|
|
|
102
110
|
|
|
103
111
|
# Spawns a send pump for one connection. Drains the shared send
|
|
@@ -129,34 +137,47 @@ module OMQ
|
|
|
129
137
|
batch = [@send_queue.dequeue]
|
|
130
138
|
drain_send_queue_capped(batch)
|
|
131
139
|
@in_flight += batch.size
|
|
140
|
+
|
|
132
141
|
begin
|
|
133
142
|
write_batch(conn, batch)
|
|
134
143
|
ensure
|
|
135
144
|
@in_flight -= batch.size
|
|
136
145
|
end
|
|
137
|
-
|
|
146
|
+
|
|
147
|
+
batch.each do |parts|
|
|
148
|
+
@engine.emit_verbose_msg_sent(conn, parts)
|
|
149
|
+
end
|
|
150
|
+
|
|
138
151
|
Async::Task.current.yield
|
|
139
152
|
end
|
|
140
153
|
end
|
|
154
|
+
|
|
141
155
|
@conn_send_tasks[conn] = task
|
|
142
156
|
@tasks << task
|
|
143
157
|
end
|
|
144
158
|
|
|
145
159
|
|
|
146
|
-
BATCH_MSG_CAP = 256
|
|
147
|
-
BATCH_BYTE_CAP = 512 * 1024
|
|
148
|
-
|
|
149
160
|
def drain_send_queue_capped(batch)
|
|
150
|
-
bytes = batch[0]
|
|
161
|
+
bytes = batch_bytes(batch[0])
|
|
151
162
|
while batch.size < BATCH_MSG_CAP && bytes < BATCH_BYTE_CAP
|
|
152
163
|
msg = @send_queue.dequeue(timeout: 0)
|
|
153
164
|
break unless msg
|
|
154
165
|
batch << msg
|
|
155
|
-
bytes += msg
|
|
166
|
+
bytes += batch_bytes(msg)
|
|
156
167
|
end
|
|
157
168
|
end
|
|
158
169
|
|
|
159
170
|
|
|
171
|
+
# Byte accounting for send-queue batching. Connection wrappers
|
|
172
|
+
# (e.g. OMQ::Ractor's MarshalConnection) may enqueue non-string
|
|
173
|
+
# parts that get transformed at write time — skip those for the
|
|
174
|
+
# fairness cap rather than crashing on #bytesize.
|
|
175
|
+
#
|
|
176
|
+
def batch_bytes(parts)
|
|
177
|
+
parts.sum { |p| p.respond_to?(:bytesize) ? p.bytesize : 0 }
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
|
|
160
181
|
def write_batch(conn, batch)
|
|
161
182
|
if batch.size == 1
|
|
162
183
|
conn.send_message(transform_send(batch[0]))
|
|
@@ -165,6 +186,7 @@ module OMQ
|
|
|
165
186
|
conn.flush
|
|
166
187
|
end
|
|
167
188
|
end
|
|
189
|
+
|
|
168
190
|
end
|
|
169
191
|
end
|
|
170
192
|
end
|
data/lib/omq/routing/router.rb
CHANGED
|
@@ -12,6 +12,13 @@ module OMQ
|
|
|
12
12
|
#
|
|
13
13
|
class Router
|
|
14
14
|
include FairRecv
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# @return [FairQueue]
|
|
18
|
+
#
|
|
19
|
+
attr_reader :recv_queue
|
|
20
|
+
|
|
21
|
+
|
|
15
22
|
# @param engine [Engine]
|
|
16
23
|
#
|
|
17
24
|
def initialize(engine)
|
|
@@ -25,10 +32,6 @@ module OMQ
|
|
|
25
32
|
end
|
|
26
33
|
|
|
27
34
|
|
|
28
|
-
# @return [FairQueue]
|
|
29
|
-
#
|
|
30
|
-
attr_reader :recv_queue
|
|
31
|
-
|
|
32
35
|
# @param connection [Connection]
|
|
33
36
|
#
|
|
34
37
|
def connection_added(connection)
|
data/lib/omq/routing/sub.rb
CHANGED
|
@@ -8,6 +8,11 @@ module OMQ
|
|
|
8
8
|
#
|
|
9
9
|
class Sub
|
|
10
10
|
|
|
11
|
+
# @return [FairQueue]
|
|
12
|
+
#
|
|
13
|
+
attr_reader :recv_queue
|
|
14
|
+
|
|
15
|
+
|
|
11
16
|
# @param engine [Engine]
|
|
12
17
|
#
|
|
13
18
|
def initialize(engine)
|
|
@@ -19,9 +24,17 @@ module OMQ
|
|
|
19
24
|
end
|
|
20
25
|
|
|
21
26
|
|
|
22
|
-
#
|
|
27
|
+
# Engine-facing recv contract. Delegates to the FairQueue.
|
|
23
28
|
#
|
|
24
|
-
|
|
29
|
+
def dequeue_recv
|
|
30
|
+
@recv_queue.dequeue
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def unblock_recv
|
|
35
|
+
@recv_queue.push(nil)
|
|
36
|
+
end
|
|
37
|
+
|
|
25
38
|
|
|
26
39
|
# @param connection [Connection]
|
|
27
40
|
#
|
|
@@ -85,6 +98,7 @@ module OMQ
|
|
|
85
98
|
@tasks.each(&:stop)
|
|
86
99
|
@tasks.clear
|
|
87
100
|
end
|
|
101
|
+
|
|
88
102
|
end
|
|
89
103
|
end
|
|
90
104
|
end
|
data/lib/omq/routing/xpub.rb
CHANGED
|
@@ -14,6 +14,11 @@ module OMQ
|
|
|
14
14
|
class XPub
|
|
15
15
|
include FanOut
|
|
16
16
|
|
|
17
|
+
# @return [Async::LimitedQueue]
|
|
18
|
+
#
|
|
19
|
+
attr_reader :recv_queue
|
|
20
|
+
|
|
21
|
+
|
|
17
22
|
# @param engine [Engine]
|
|
18
23
|
#
|
|
19
24
|
def initialize(engine)
|
|
@@ -24,9 +29,17 @@ module OMQ
|
|
|
24
29
|
end
|
|
25
30
|
|
|
26
31
|
|
|
27
|
-
#
|
|
32
|
+
# Engine-facing recv contract. Delegates to the bounded queue.
|
|
28
33
|
#
|
|
29
|
-
|
|
34
|
+
def dequeue_recv
|
|
35
|
+
@recv_queue.dequeue
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def unblock_recv
|
|
40
|
+
@recv_queue.push(nil)
|
|
41
|
+
end
|
|
42
|
+
|
|
30
43
|
|
|
31
44
|
# @param connection [Connection]
|
|
32
45
|
#
|
|
@@ -63,8 +76,10 @@ module OMQ
|
|
|
63
76
|
@tasks.clear
|
|
64
77
|
end
|
|
65
78
|
|
|
79
|
+
|
|
66
80
|
private
|
|
67
81
|
|
|
82
|
+
|
|
68
83
|
# Expose subscription to application as data message.
|
|
69
84
|
#
|
|
70
85
|
def on_subscribe(conn, prefix)
|
|
@@ -79,6 +94,7 @@ module OMQ
|
|
|
79
94
|
super
|
|
80
95
|
@recv_queue.enqueue(["\x00#{prefix}".b])
|
|
81
96
|
end
|
|
97
|
+
|
|
82
98
|
end
|
|
83
99
|
end
|
|
84
100
|
end
|
data/lib/omq/routing/xsub.rb
CHANGED
|
@@ -10,6 +10,11 @@ module OMQ
|
|
|
10
10
|
#
|
|
11
11
|
class XSub
|
|
12
12
|
|
|
13
|
+
# @return [FairQueue]
|
|
14
|
+
#
|
|
15
|
+
attr_reader :recv_queue
|
|
16
|
+
|
|
17
|
+
|
|
13
18
|
# @param engine [Engine]
|
|
14
19
|
#
|
|
15
20
|
def initialize(engine)
|
|
@@ -22,9 +27,17 @@ module OMQ
|
|
|
22
27
|
end
|
|
23
28
|
|
|
24
29
|
|
|
25
|
-
#
|
|
30
|
+
# Engine-facing recv contract. Delegates to the FairQueue.
|
|
26
31
|
#
|
|
27
|
-
|
|
32
|
+
def dequeue_recv
|
|
33
|
+
@recv_queue.dequeue
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def unblock_recv
|
|
38
|
+
@recv_queue.push(nil)
|
|
39
|
+
end
|
|
40
|
+
|
|
28
41
|
|
|
29
42
|
# @param connection [Connection]
|
|
30
43
|
#
|
|
@@ -58,7 +71,9 @@ module OMQ
|
|
|
58
71
|
# @param parts [Array<String>]
|
|
59
72
|
#
|
|
60
73
|
def enqueue(parts)
|
|
61
|
-
@connections.each
|
|
74
|
+
@connections.each do |conn|
|
|
75
|
+
@conn_queues[conn]&.enqueue(parts)
|
|
76
|
+
end
|
|
62
77
|
end
|
|
63
78
|
|
|
64
79
|
|
|
@@ -78,16 +93,21 @@ module OMQ
|
|
|
78
93
|
@conn_queues.values.all?(&:empty?)
|
|
79
94
|
end
|
|
80
95
|
|
|
96
|
+
|
|
81
97
|
private
|
|
82
98
|
|
|
99
|
+
|
|
83
100
|
def start_conn_send_pump(conn, q)
|
|
84
101
|
task = @engine.spawn_conn_pump_task(conn, annotation: "send pump") do
|
|
85
102
|
loop do
|
|
86
103
|
parts = q.dequeue
|
|
87
104
|
frame = parts.first&.b
|
|
105
|
+
|
|
88
106
|
next if frame.nil? || frame.empty?
|
|
107
|
+
|
|
89
108
|
flag = frame.getbyte(0)
|
|
90
109
|
prefix = frame.byteslice(1..) || "".b
|
|
110
|
+
|
|
91
111
|
case flag
|
|
92
112
|
when 0x01
|
|
93
113
|
conn.send_command(Protocol::ZMTP::Codec::Command.subscribe(prefix))
|
|
@@ -96,9 +116,11 @@ module OMQ
|
|
|
96
116
|
end
|
|
97
117
|
end
|
|
98
118
|
end
|
|
119
|
+
|
|
99
120
|
@conn_send_tasks[conn] = task
|
|
100
121
|
@tasks << task
|
|
101
122
|
end
|
|
123
|
+
|
|
102
124
|
end
|
|
103
125
|
end
|
|
104
126
|
end
|
data/lib/omq/routing.rb
CHANGED
data/lib/omq/single_frame.rb
CHANGED
data/lib/omq/socket.rb
CHANGED
|
@@ -6,6 +6,30 @@ module OMQ
|
|
|
6
6
|
# Socket base class.
|
|
7
7
|
#
|
|
8
8
|
class Socket
|
|
9
|
+
extend Forwardable
|
|
10
|
+
|
|
11
|
+
# Creates a new socket and binds it to the given endpoint.
|
|
12
|
+
#
|
|
13
|
+
# @param endpoint [String]
|
|
14
|
+
# @param opts [Hash] keyword arguments forwarded to {#initialize}
|
|
15
|
+
# @return [Socket]
|
|
16
|
+
#
|
|
17
|
+
def self.bind(endpoint, **opts)
|
|
18
|
+
new("@#{endpoint}", **opts)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# Creates a new socket and connects it to the given endpoint.
|
|
23
|
+
#
|
|
24
|
+
# @param endpoint [String]
|
|
25
|
+
# @param opts [Hash] keyword arguments forwarded to {#initialize}
|
|
26
|
+
# @return [Socket]
|
|
27
|
+
#
|
|
28
|
+
def self.connect(endpoint, **opts)
|
|
29
|
+
new(">#{endpoint}", **opts)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
|
|
9
33
|
# @return [Options]
|
|
10
34
|
#
|
|
11
35
|
attr_reader :options
|
|
@@ -16,10 +40,15 @@ module OMQ
|
|
|
16
40
|
attr_reader :last_tcp_port
|
|
17
41
|
|
|
18
42
|
|
|
19
|
-
#
|
|
43
|
+
# @return [Engine] the socket's engine. Exposed for peer tooling
|
|
44
|
+
# (omq-cli, omq-ffi, omq-ractor) that needs to reach into the
|
|
45
|
+
# socket's internals — not part of the stable user API.
|
|
20
46
|
#
|
|
21
|
-
|
|
47
|
+
attr_reader :engine
|
|
22
48
|
|
|
49
|
+
|
|
50
|
+
# Delegate socket option accessors to @options.
|
|
51
|
+
#
|
|
23
52
|
def_delegators :@options,
|
|
24
53
|
:send_hwm, :send_hwm=,
|
|
25
54
|
:recv_hwm, :recv_hwm=,
|
|
@@ -42,28 +71,6 @@ module OMQ
|
|
|
42
71
|
:mechanism, :mechanism=
|
|
43
72
|
|
|
44
73
|
|
|
45
|
-
# Creates a new socket and binds it to the given endpoint.
|
|
46
|
-
#
|
|
47
|
-
# @param endpoint [String]
|
|
48
|
-
# @param opts [Hash] keyword arguments forwarded to {#initialize}
|
|
49
|
-
# @return [Socket]
|
|
50
|
-
#
|
|
51
|
-
def self.bind(endpoint, **opts)
|
|
52
|
-
new("@#{endpoint}", **opts)
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
# Creates a new socket and connects it to the given endpoint.
|
|
57
|
-
#
|
|
58
|
-
# @param endpoint [String]
|
|
59
|
-
# @param opts [Hash] keyword arguments forwarded to {#initialize}
|
|
60
|
-
# @return [Socket]
|
|
61
|
-
#
|
|
62
|
-
def self.connect(endpoint, **opts)
|
|
63
|
-
new(">#{endpoint}", **opts)
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
|
|
67
74
|
# @param endpoints [String, nil] optional endpoint with prefix convention
|
|
68
75
|
# (+@+ for bind, +>+ for connect, plain uses subclass default)
|
|
69
76
|
# @param linger [Integer] linger period in seconds (default 0)
|
|
@@ -134,19 +141,27 @@ module OMQ
|
|
|
134
141
|
|
|
135
142
|
|
|
136
143
|
# @return [Async::Promise] resolves when first peer completes handshake
|
|
137
|
-
def peer_connected
|
|
144
|
+
def peer_connected
|
|
145
|
+
@engine.peer_connected
|
|
146
|
+
end
|
|
138
147
|
|
|
139
148
|
|
|
140
149
|
# @return [Async::Promise] resolves when first subscriber joins (PUB/XPUB only)
|
|
141
|
-
def subscriber_joined
|
|
150
|
+
def subscriber_joined
|
|
151
|
+
@engine.routing.subscriber_joined
|
|
152
|
+
end
|
|
142
153
|
|
|
143
154
|
|
|
144
155
|
# @return [Async::Promise] resolves when all peers disconnect (after having had peers)
|
|
145
|
-
def all_peers_gone
|
|
156
|
+
def all_peers_gone
|
|
157
|
+
@engine.all_peers_gone
|
|
158
|
+
end
|
|
146
159
|
|
|
147
160
|
|
|
148
161
|
# @return [Integer] current number of peer connections
|
|
149
|
-
def connection_count
|
|
162
|
+
def connection_count
|
|
163
|
+
@engine.connections.size
|
|
164
|
+
end
|
|
150
165
|
|
|
151
166
|
|
|
152
167
|
# Signals end-of-stream on the receive side. A subsequent
|
|
@@ -263,6 +278,7 @@ module OMQ
|
|
|
263
278
|
#
|
|
264
279
|
def attach_endpoints(endpoints, default:)
|
|
265
280
|
return unless endpoints
|
|
281
|
+
|
|
266
282
|
case endpoints
|
|
267
283
|
when /\A@(.+)\z/
|
|
268
284
|
bind($1)
|
|
@@ -311,5 +327,6 @@ module OMQ
|
|
|
311
327
|
def ensure_parent_task(parent: nil)
|
|
312
328
|
@engine.capture_parent_task(parent: parent)
|
|
313
329
|
end
|
|
330
|
+
|
|
314
331
|
end
|
|
315
332
|
end
|
|
@@ -110,14 +110,18 @@ module OMQ
|
|
|
110
110
|
|
|
111
111
|
# @return [Boolean] always false; inproc pipes are never encrypted
|
|
112
112
|
#
|
|
113
|
-
def encrypted?
|
|
113
|
+
def encrypted?
|
|
114
|
+
false
|
|
115
|
+
end
|
|
114
116
|
|
|
115
117
|
|
|
116
118
|
# No-op — inproc has no IO buffer to flush.
|
|
117
119
|
#
|
|
118
120
|
# @return [nil]
|
|
119
121
|
#
|
|
120
|
-
def flush
|
|
122
|
+
def flush
|
|
123
|
+
nil
|
|
124
|
+
end
|
|
121
125
|
|
|
122
126
|
|
|
123
127
|
# Receives a multi-frame message.
|
data/lib/omq/transport/tcp.rb
CHANGED
data/lib/omq/version.rb
CHANGED
data/lib/omq/writable.rb
CHANGED
|
@@ -7,6 +7,11 @@ module OMQ
|
|
|
7
7
|
#
|
|
8
8
|
module Writable
|
|
9
9
|
include QueueWritable
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
EMPTY_PART = "".b.freeze
|
|
13
|
+
|
|
14
|
+
|
|
10
15
|
# Sends a message.
|
|
11
16
|
#
|
|
12
17
|
# @param message [String, Array<String>] message parts
|
|
@@ -33,8 +38,20 @@ module OMQ
|
|
|
33
38
|
send(message)
|
|
34
39
|
end
|
|
35
40
|
|
|
41
|
+
|
|
42
|
+
# Waits until the socket is writable.
|
|
43
|
+
#
|
|
44
|
+
# @param timeout [Numeric, nil] timeout in seconds
|
|
45
|
+
# @return [true]
|
|
46
|
+
#
|
|
47
|
+
def wait_writable(timeout = @options.write_timeout)
|
|
48
|
+
true
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
|
|
36
52
|
private
|
|
37
53
|
|
|
54
|
+
|
|
38
55
|
# Converts a message into a frozen array of frozen binary strings.
|
|
39
56
|
#
|
|
40
57
|
# @param message [String, Array<String>]
|
|
@@ -44,21 +61,23 @@ module OMQ
|
|
|
44
61
|
parts = message.is_a?(Array) ? message : [message]
|
|
45
62
|
raise ArgumentError, "message has no parts" if parts.empty?
|
|
46
63
|
|
|
47
|
-
|
|
64
|
+
all_ready = parts.all? { |p| p.is_a?(String) && p.frozen? && p.encoding == Encoding::BINARY }
|
|
65
|
+
|
|
66
|
+
# Already a frozen array of frozen binary strings → return as-is.
|
|
67
|
+
return parts if all_ready && parts.frozen?
|
|
68
|
+
|
|
69
|
+
# Items are ready; just freeze the outer array.
|
|
70
|
+
return parts.freeze if all_ready
|
|
71
|
+
|
|
72
|
+
# Items need conversion. Mutate in place when we can.
|
|
48
73
|
if parts.frozen?
|
|
49
|
-
|
|
50
|
-
parts = parts.map { |p| frozen_binary(p) }
|
|
74
|
+
parts.map { |p| frozen_binary(p) }.freeze
|
|
51
75
|
else
|
|
52
|
-
|
|
53
|
-
parts.map! { |p| frozen_binary(p) }
|
|
54
|
-
end
|
|
76
|
+
parts.map! { |p| frozen_binary(p) }.freeze
|
|
55
77
|
end
|
|
56
|
-
parts.freeze
|
|
57
78
|
end
|
|
58
79
|
|
|
59
80
|
|
|
60
|
-
EMPTY_PART = "".b.freeze
|
|
61
|
-
|
|
62
81
|
def frozen_binary(obj)
|
|
63
82
|
return EMPTY_PART if obj.nil?
|
|
64
83
|
s = obj.to_s
|
|
@@ -66,15 +85,5 @@ module OMQ
|
|
|
66
85
|
s.b.freeze
|
|
67
86
|
end
|
|
68
87
|
|
|
69
|
-
public
|
|
70
|
-
|
|
71
|
-
# Waits until the socket is writable.
|
|
72
|
-
#
|
|
73
|
-
# @param timeout [Numeric, nil] timeout in seconds
|
|
74
|
-
# @return [true]
|
|
75
|
-
#
|
|
76
|
-
def wait_writable(timeout = @options.write_timeout)
|
|
77
|
-
true
|
|
78
|
-
end
|
|
79
88
|
end
|
|
80
89
|
end
|