omq 0.11.0 → 0.13.0
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 +143 -0
- data/README.md +3 -1
- data/lib/omq/drop_queue.rb +54 -0
- data/lib/omq/engine/connection_setup.rb +47 -0
- data/lib/omq/engine/heartbeat.rb +40 -0
- data/lib/omq/engine/reconnect.rb +56 -0
- data/lib/omq/engine/recv_pump.rb +76 -0
- data/lib/omq/engine.rb +145 -371
- data/lib/omq/monitor_event.rb +16 -0
- data/lib/omq/options.rb +5 -3
- data/lib/omq/pub_sub.rb +9 -8
- data/lib/omq/routing/conn_send_pump.rb +36 -0
- data/lib/omq/routing/dealer.rb +8 -10
- data/lib/omq/routing/fair_queue.rb +144 -0
- data/lib/omq/routing/fair_recv.rb +27 -0
- data/lib/omq/routing/fan_out.rb +116 -63
- data/lib/omq/routing/pair.rb +39 -20
- data/lib/omq/routing/pub.rb +5 -7
- data/lib/omq/routing/pull.rb +5 -4
- data/lib/omq/routing/push.rb +3 -10
- data/lib/omq/routing/rep.rb +31 -51
- data/lib/omq/routing/req.rb +15 -12
- data/lib/omq/routing/round_robin.rb +82 -72
- data/lib/omq/routing/router.rb +23 -48
- data/lib/omq/routing/sub.rb +8 -6
- data/lib/omq/routing/xpub.rb +8 -4
- data/lib/omq/routing/xsub.rb +43 -27
- data/lib/omq/routing.rb +44 -11
- data/lib/omq/socket.rb +46 -5
- data/lib/omq/transport/inproc/direct_pipe.rb +162 -0
- data/lib/omq/transport/inproc.rb +37 -200
- data/lib/omq/transport/ipc.rb +16 -4
- data/lib/omq/transport/tcp.rb +31 -8
- data/lib/omq/version.rb +1 -1
- data/lib/omq.rb +5 -19
- metadata +11 -16
- data/lib/omq/channel.rb +0 -14
- data/lib/omq/client_server.rb +0 -37
- data/lib/omq/peer.rb +0 -26
- data/lib/omq/radio_dish.rb +0 -74
- data/lib/omq/routing/channel.rb +0 -83
- data/lib/omq/routing/client.rb +0 -56
- data/lib/omq/routing/dish.rb +0 -78
- data/lib/omq/routing/gather.rb +0 -46
- data/lib/omq/routing/peer.rb +0 -101
- data/lib/omq/routing/radio.rb +0 -150
- data/lib/omq/routing/scatter.rb +0 -82
- data/lib/omq/routing/server.rb +0 -101
- data/lib/omq/scatter_gather.rb +0 -23
- data/lib/omq/single_frame.rb +0 -18
- data/lib/omq/transport/tls.rb +0 -146
data/lib/omq/transport/inproc.rb
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require "async"
|
|
4
4
|
require "async/queue"
|
|
5
|
+
require_relative "inproc/direct_pipe"
|
|
5
6
|
|
|
6
7
|
module OMQ
|
|
7
8
|
module Transport
|
|
@@ -54,25 +55,7 @@ module OMQ
|
|
|
54
55
|
#
|
|
55
56
|
def connect(endpoint, engine)
|
|
56
57
|
bound_engine = @mutex.synchronize { @registry[endpoint] }
|
|
57
|
-
|
|
58
|
-
unless bound_engine
|
|
59
|
-
# Endpoint not bound yet. Wait with timeout derived from
|
|
60
|
-
# reconnect_interval. If it doesn't appear, silently return —
|
|
61
|
-
# matching ZMQ 4.x behavior where inproc connect to an
|
|
62
|
-
# unbound endpoint succeeds but messages go nowhere.
|
|
63
|
-
# A background task retries periodically.
|
|
64
|
-
ri = engine.options.reconnect_interval
|
|
65
|
-
timeout = ri.is_a?(Range) ? ri.begin : ri
|
|
66
|
-
promise = Async::Promise.new
|
|
67
|
-
@mutex.synchronize { @waiters[endpoint] << promise }
|
|
68
|
-
unless promise.wait?(timeout: timeout)
|
|
69
|
-
@mutex.synchronize { @waiters[endpoint].delete(promise) }
|
|
70
|
-
start_connect_retry(endpoint, engine)
|
|
71
|
-
return
|
|
72
|
-
end
|
|
73
|
-
bound_engine = @mutex.synchronize { @registry[endpoint] }
|
|
74
|
-
end
|
|
75
|
-
|
|
58
|
+
bound_engine ||= await_bind(endpoint, engine) or return
|
|
76
59
|
establish_link(engine, bound_engine, endpoint)
|
|
77
60
|
end
|
|
78
61
|
|
|
@@ -112,41 +95,51 @@ module OMQ
|
|
|
112
95
|
def establish_link(client_engine, server_engine, endpoint)
|
|
113
96
|
client_type = client_engine.socket_type
|
|
114
97
|
server_type = server_engine.socket_type
|
|
115
|
-
|
|
116
98
|
unless Protocol::ZMTP::VALID_PEERS[client_type]&.include?(server_type)
|
|
117
99
|
raise Protocol::ZMTP::Error,
|
|
118
100
|
"incompatible socket types: #{client_type} cannot connect to #{server_type}"
|
|
119
101
|
end
|
|
102
|
+
needs_cmds = needs_commands?(client_engine, server_engine, client_type, server_type)
|
|
103
|
+
client_pipe, server_pipe = make_pipe_pair(client_engine, server_engine, client_type, server_type, needs_cmds)
|
|
104
|
+
client_engine.connection_ready(client_pipe, endpoint: endpoint)
|
|
105
|
+
server_engine.connection_ready(server_pipe, endpoint: endpoint)
|
|
106
|
+
end
|
|
120
107
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
COMMAND_TYPES.include?(server_type)
|
|
108
|
+
def needs_commands?(ce, se, ct, st)
|
|
109
|
+
COMMAND_TYPES.include?(ct) || COMMAND_TYPES.include?(st) ||
|
|
110
|
+
ce.options.qos >= 1 || se.options.qos >= 1
|
|
111
|
+
end
|
|
126
112
|
|
|
127
|
-
|
|
113
|
+
def make_pipe_pair(ce, se, ct, st, needs_cmds)
|
|
114
|
+
if needs_cmds
|
|
128
115
|
a_to_b = Async::Queue.new
|
|
129
116
|
b_to_a = Async::Queue.new
|
|
130
117
|
end
|
|
118
|
+
client = DirectPipe.new(send_queue: needs_cmds ? a_to_b : nil,
|
|
119
|
+
receive_queue: needs_cmds ? b_to_a : nil,
|
|
120
|
+
peer_identity: se.options.identity, peer_type: st.to_s)
|
|
121
|
+
server = DirectPipe.new(send_queue: needs_cmds ? b_to_a : nil,
|
|
122
|
+
receive_queue: needs_cmds ? a_to_b : nil,
|
|
123
|
+
peer_identity: ce.options.identity, peer_type: ct.to_s)
|
|
124
|
+
client.peer = server
|
|
125
|
+
server.peer = client
|
|
126
|
+
[client, server]
|
|
127
|
+
end
|
|
131
128
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
server_pipe.peer = client_pipe
|
|
147
|
-
|
|
148
|
-
client_engine.connection_ready(client_pipe, endpoint: endpoint)
|
|
149
|
-
server_engine.connection_ready(server_pipe, endpoint: endpoint)
|
|
129
|
+
def await_bind(endpoint, engine)
|
|
130
|
+
# Endpoint not bound yet — wait briefly then start background retry.
|
|
131
|
+
# Matches ZMQ 4.x: connect to unbound inproc succeeds silently.
|
|
132
|
+
ri = engine.options.reconnect_interval
|
|
133
|
+
timeout = ri.is_a?(Range) ? ri.begin : ri
|
|
134
|
+
promise = Async::Promise.new
|
|
135
|
+
@mutex.synchronize { @waiters[endpoint] << promise }
|
|
136
|
+
if promise.wait?(timeout: timeout)
|
|
137
|
+
@mutex.synchronize { @registry[endpoint] }
|
|
138
|
+
else
|
|
139
|
+
@mutex.synchronize { @waiters[endpoint].delete(promise) }
|
|
140
|
+
start_connect_retry(endpoint, engine)
|
|
141
|
+
nil
|
|
142
|
+
end
|
|
150
143
|
end
|
|
151
144
|
|
|
152
145
|
|
|
@@ -194,162 +187,6 @@ module OMQ
|
|
|
194
187
|
end
|
|
195
188
|
end
|
|
196
189
|
|
|
197
|
-
# A direct in-process pipe that transfers Ruby arrays through queues.
|
|
198
|
-
#
|
|
199
|
-
# Implements the same interface as Connection so routing strategies
|
|
200
|
-
# can use it transparently.
|
|
201
|
-
#
|
|
202
|
-
# When a routing strategy sets {#direct_recv_queue} on a pipe,
|
|
203
|
-
# {#send_message} enqueues directly into the peer's recv queue,
|
|
204
|
-
# bypassing the intermediate pipe queues and the recv pump task.
|
|
205
|
-
# This reduces inproc from 3 queue hops to 2 (send_queue →
|
|
206
|
-
# recv_queue), eliminating the internal pipe queue in between.
|
|
207
|
-
#
|
|
208
|
-
class DirectPipe
|
|
209
|
-
# @return [String] peer's socket type
|
|
210
|
-
#
|
|
211
|
-
attr_reader :peer_socket_type
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
# @return [String] peer's identity
|
|
215
|
-
#
|
|
216
|
-
attr_reader :peer_identity
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
# @return [DirectPipe, nil] the other end of this pipe pair
|
|
220
|
-
#
|
|
221
|
-
attr_accessor :peer
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
# @return [Async::LimitedQueue, nil] when set, {#send_message}
|
|
225
|
-
# enqueues directly here instead of using the internal queue
|
|
226
|
-
#
|
|
227
|
-
attr_reader :direct_recv_queue
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
# @return [Proc, nil] optional transform applied before
|
|
231
|
-
# enqueuing into {#direct_recv_queue}
|
|
232
|
-
#
|
|
233
|
-
attr_accessor :direct_recv_transform
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
# @param send_queue [Async::Queue, nil] outgoing command queue
|
|
237
|
-
# (nil for non-PUB/SUB types that don't exchange commands)
|
|
238
|
-
# @param receive_queue [Async::Queue, nil] incoming command queue
|
|
239
|
-
# @param peer_identity [String]
|
|
240
|
-
# @param peer_type [String]
|
|
241
|
-
#
|
|
242
|
-
def initialize(send_queue: nil, receive_queue: nil, peer_identity:, peer_type:)
|
|
243
|
-
@send_queue = send_queue
|
|
244
|
-
@receive_queue = receive_queue
|
|
245
|
-
@peer_identity = peer_identity || "".b
|
|
246
|
-
@peer_socket_type = peer_type
|
|
247
|
-
@closed = false
|
|
248
|
-
@peer = nil
|
|
249
|
-
@direct_recv_queue = nil
|
|
250
|
-
@direct_recv_transform = nil
|
|
251
|
-
@pending_direct = nil
|
|
252
|
-
end
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
# Sets the direct recv queue. Drains any messages that were
|
|
256
|
-
# buffered before the queue was available.
|
|
257
|
-
#
|
|
258
|
-
def direct_recv_queue=(queue)
|
|
259
|
-
@direct_recv_queue = queue
|
|
260
|
-
if queue && @pending_direct
|
|
261
|
-
@pending_direct.each do |msg|
|
|
262
|
-
queue.enqueue(msg)
|
|
263
|
-
end
|
|
264
|
-
@pending_direct = nil
|
|
265
|
-
end
|
|
266
|
-
end
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
# Sends a multi-frame message.
|
|
270
|
-
#
|
|
271
|
-
# When {#direct_recv_queue} is set (inproc fast path), the
|
|
272
|
-
# message is delivered directly to the peer's recv queue,
|
|
273
|
-
# skipping the internal pipe queues and the recv pump.
|
|
274
|
-
#
|
|
275
|
-
# @param parts [Array<String>]
|
|
276
|
-
# @return [void]
|
|
277
|
-
#
|
|
278
|
-
def send_message(parts)
|
|
279
|
-
raise IOError, "closed" if @closed
|
|
280
|
-
if @direct_recv_queue
|
|
281
|
-
msg = @direct_recv_transform ? @direct_recv_transform.call(parts).freeze : parts
|
|
282
|
-
@direct_recv_queue.enqueue(msg)
|
|
283
|
-
elsif @send_queue
|
|
284
|
-
@send_queue.enqueue(parts)
|
|
285
|
-
else
|
|
286
|
-
msg = @direct_recv_transform ? @direct_recv_transform.call(parts).freeze : parts
|
|
287
|
-
(@pending_direct ||= []) << msg
|
|
288
|
-
end
|
|
289
|
-
end
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
alias write_message send_message
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
# No-op — inproc has no IO buffer to flush.
|
|
296
|
-
#
|
|
297
|
-
# @return [void]
|
|
298
|
-
#
|
|
299
|
-
def flush = nil
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
# Receives a multi-frame message.
|
|
303
|
-
#
|
|
304
|
-
# @return [Array<String>]
|
|
305
|
-
# @raise [EOFError] if closed
|
|
306
|
-
#
|
|
307
|
-
def receive_message
|
|
308
|
-
msg = @receive_queue.dequeue
|
|
309
|
-
raise EOFError, "connection closed" if msg.nil?
|
|
310
|
-
msg
|
|
311
|
-
end
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
# Sends a command via the internal command queue.
|
|
315
|
-
# Only available for PUB/SUB-family pipes.
|
|
316
|
-
#
|
|
317
|
-
# @param command [Protocol::ZMTP::Codec::Command]
|
|
318
|
-
# @return [void]
|
|
319
|
-
#
|
|
320
|
-
def send_command(command)
|
|
321
|
-
raise IOError, "closed" if @closed
|
|
322
|
-
@send_queue.enqueue([:command, command])
|
|
323
|
-
end
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
# Reads one command frame from the internal command queue.
|
|
327
|
-
# Used by PUB/XPUB subscription listeners.
|
|
328
|
-
#
|
|
329
|
-
# @return [Protocol::ZMTP::Codec::Frame]
|
|
330
|
-
#
|
|
331
|
-
def read_frame
|
|
332
|
-
loop do
|
|
333
|
-
item = @receive_queue.dequeue
|
|
334
|
-
raise EOFError, "connection closed" if item.nil?
|
|
335
|
-
if item.is_a?(Array) && item.first == :command
|
|
336
|
-
cmd = item[1]
|
|
337
|
-
return Protocol::ZMTP::Codec::Frame.new(cmd.to_body, command: true)
|
|
338
|
-
end
|
|
339
|
-
end
|
|
340
|
-
end
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
# Closes this pipe end.
|
|
344
|
-
#
|
|
345
|
-
# @return [void]
|
|
346
|
-
#
|
|
347
|
-
def close
|
|
348
|
-
return if @closed
|
|
349
|
-
@closed = true
|
|
350
|
-
@send_queue&.enqueue(nil) # close sentinel
|
|
351
|
-
end
|
|
352
|
-
end
|
|
353
190
|
end
|
|
354
191
|
end
|
|
355
192
|
end
|
data/lib/omq/transport/ipc.rb
CHANGED
|
@@ -92,12 +92,24 @@ module OMQ
|
|
|
92
92
|
end
|
|
93
93
|
|
|
94
94
|
|
|
95
|
-
#
|
|
95
|
+
# Spawns an accept loop task under +parent_task+.
|
|
96
|
+
# Yields an IO::Stream-wrapped client socket for each accepted connection.
|
|
96
97
|
#
|
|
97
|
-
# @param
|
|
98
|
+
# @param parent_task [Async::Task]
|
|
99
|
+
# @yieldparam io [IO::Stream::Buffered]
|
|
98
100
|
#
|
|
99
|
-
def
|
|
100
|
-
@task =
|
|
101
|
+
def start_accept_loops(parent_task, &on_accepted)
|
|
102
|
+
@task = parent_task.async(transient: true, annotation: "ipc accept #{@endpoint}") do
|
|
103
|
+
loop do
|
|
104
|
+
client = @server.accept
|
|
105
|
+
Async::Task.current.defer_stop { on_accepted.call(IO::Stream::Buffered.wrap(client)) }
|
|
106
|
+
end
|
|
107
|
+
rescue Async::Stop
|
|
108
|
+
rescue IOError
|
|
109
|
+
# server closed
|
|
110
|
+
ensure
|
|
111
|
+
@server.close rescue nil
|
|
112
|
+
end
|
|
101
113
|
end
|
|
102
114
|
|
|
103
115
|
|
data/lib/omq/transport/tcp.rb
CHANGED
|
@@ -17,7 +17,7 @@ module OMQ
|
|
|
17
17
|
# @return [Listener]
|
|
18
18
|
#
|
|
19
19
|
def bind(endpoint, engine)
|
|
20
|
-
host, port = parse_endpoint(endpoint)
|
|
20
|
+
host, port = self.parse_endpoint(endpoint)
|
|
21
21
|
host = "0.0.0.0" if host == "*"
|
|
22
22
|
|
|
23
23
|
addrs = Addrinfo.getaddrinfo(host, port, nil, :STREAM, nil, ::Socket::AI_PASSIVE)
|
|
@@ -43,14 +43,23 @@ module OMQ
|
|
|
43
43
|
# @param engine [Engine]
|
|
44
44
|
# @return [void]
|
|
45
45
|
#
|
|
46
|
+
# Validates that the endpoint's host can be resolved.
|
|
47
|
+
#
|
|
48
|
+
# @param endpoint [String]
|
|
49
|
+
# @return [void]
|
|
50
|
+
#
|
|
51
|
+
def validate_endpoint!(endpoint)
|
|
52
|
+
host, _port = parse_endpoint(endpoint)
|
|
53
|
+
Addrinfo.getaddrinfo(host, nil, nil, :STREAM) if host
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
|
|
46
57
|
def connect(endpoint, engine)
|
|
47
|
-
host, port = parse_endpoint(endpoint)
|
|
58
|
+
host, port = self.parse_endpoint(endpoint)
|
|
48
59
|
sock = TCPSocket.new(host, port)
|
|
49
60
|
engine.handle_connected(IO::Stream::Buffered.wrap(sock), endpoint: endpoint)
|
|
50
61
|
end
|
|
51
62
|
|
|
52
|
-
private
|
|
53
|
-
|
|
54
63
|
# Parses a TCP endpoint URI into host and port.
|
|
55
64
|
#
|
|
56
65
|
# @param endpoint [String]
|
|
@@ -90,12 +99,26 @@ module OMQ
|
|
|
90
99
|
end
|
|
91
100
|
|
|
92
101
|
|
|
93
|
-
#
|
|
102
|
+
# Spawns accept loop tasks under +parent_task+.
|
|
103
|
+
# Yields an IO::Stream-wrapped client socket for each accepted connection.
|
|
94
104
|
#
|
|
95
|
-
# @param
|
|
105
|
+
# @param parent_task [Async::Task]
|
|
106
|
+
# @yieldparam io [IO::Stream::Buffered]
|
|
96
107
|
#
|
|
97
|
-
def
|
|
98
|
-
@tasks =
|
|
108
|
+
def start_accept_loops(parent_task, &on_accepted)
|
|
109
|
+
@tasks = @servers.map do |server|
|
|
110
|
+
parent_task.async(transient: true, annotation: "tcp accept #{@endpoint}") do
|
|
111
|
+
loop do
|
|
112
|
+
client = server.accept
|
|
113
|
+
Async::Task.current.defer_stop { on_accepted.call(IO::Stream::Buffered.wrap(client)) }
|
|
114
|
+
end
|
|
115
|
+
rescue Async::Stop
|
|
116
|
+
rescue IOError
|
|
117
|
+
# server closed
|
|
118
|
+
ensure
|
|
119
|
+
server.close rescue nil
|
|
120
|
+
end
|
|
121
|
+
end
|
|
99
122
|
end
|
|
100
123
|
|
|
101
124
|
|
data/lib/omq/version.rb
CHANGED
data/lib/omq.rb
CHANGED
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
|
|
9
9
|
require "protocol/zmtp"
|
|
10
10
|
require "io/stream"
|
|
11
|
-
require "openssl"
|
|
12
11
|
|
|
13
12
|
require_relative "omq/version"
|
|
13
|
+
require_relative "omq/monitor_event"
|
|
14
14
|
|
|
15
15
|
module OMQ
|
|
16
16
|
# Raised when an internal pump task crashes unexpectedly.
|
|
@@ -19,6 +19,8 @@ module OMQ
|
|
|
19
19
|
class SocketDeadError < RuntimeError; end
|
|
20
20
|
|
|
21
21
|
# Errors raised when a peer disconnects or resets the connection.
|
|
22
|
+
# Not frozen at load time — transport plugins append to this before
|
|
23
|
+
# the first bind/connect, which freezes both arrays.
|
|
22
24
|
CONNECTION_LOST = [
|
|
23
25
|
EOFError,
|
|
24
26
|
IOError,
|
|
@@ -27,8 +29,7 @@ module OMQ
|
|
|
27
29
|
Errno::ECONNABORTED,
|
|
28
30
|
Errno::ENOTCONN,
|
|
29
31
|
IO::Stream::ConnectionResetError,
|
|
30
|
-
|
|
31
|
-
].freeze
|
|
32
|
+
]
|
|
32
33
|
|
|
33
34
|
# Errors raised when a peer cannot be reached.
|
|
34
35
|
CONNECTION_FAILED = [
|
|
@@ -38,13 +39,12 @@ module OMQ
|
|
|
38
39
|
Errno::EHOSTUNREACH,
|
|
39
40
|
Errno::ENETUNREACH,
|
|
40
41
|
Socket::ResolutionError,
|
|
41
|
-
]
|
|
42
|
+
]
|
|
42
43
|
end
|
|
43
44
|
|
|
44
45
|
# Transport
|
|
45
46
|
require_relative "omq/transport/inproc"
|
|
46
47
|
require_relative "omq/transport/tcp"
|
|
47
|
-
require_relative "omq/transport/tls"
|
|
48
48
|
require_relative "omq/transport/ipc"
|
|
49
49
|
|
|
50
50
|
# Core
|
|
@@ -64,15 +64,6 @@ require_relative "omq/routing/xpub"
|
|
|
64
64
|
require_relative "omq/routing/xsub"
|
|
65
65
|
require_relative "omq/routing/push"
|
|
66
66
|
require_relative "omq/routing/pull"
|
|
67
|
-
require_relative "omq/routing/scatter"
|
|
68
|
-
require_relative "omq/routing/gather"
|
|
69
|
-
require_relative "omq/routing/channel"
|
|
70
|
-
require_relative "omq/routing/client"
|
|
71
|
-
require_relative "omq/routing/server"
|
|
72
|
-
require_relative "omq/routing/radio"
|
|
73
|
-
require_relative "omq/routing/dish"
|
|
74
|
-
require_relative "omq/routing/peer"
|
|
75
|
-
require_relative "omq/single_frame"
|
|
76
67
|
require_relative "omq/engine"
|
|
77
68
|
require_relative "omq/queue_interface"
|
|
78
69
|
require_relative "omq/readable"
|
|
@@ -85,11 +76,6 @@ require_relative "omq/router_dealer"
|
|
|
85
76
|
require_relative "omq/pub_sub"
|
|
86
77
|
require_relative "omq/push_pull"
|
|
87
78
|
require_relative "omq/pair"
|
|
88
|
-
require_relative "omq/scatter_gather"
|
|
89
|
-
require_relative "omq/channel"
|
|
90
|
-
require_relative "omq/client_server"
|
|
91
|
-
require_relative "omq/radio_dish"
|
|
92
|
-
require_relative "omq/peer"
|
|
93
79
|
|
|
94
80
|
# For the purists.
|
|
95
81
|
ØMQ = OMQ
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: omq
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.13.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Patrik Wenger
|
|
@@ -65,49 +65,44 @@ files:
|
|
|
65
65
|
- LICENSE
|
|
66
66
|
- README.md
|
|
67
67
|
- lib/omq.rb
|
|
68
|
-
- lib/omq/
|
|
69
|
-
- lib/omq/client_server.rb
|
|
68
|
+
- lib/omq/drop_queue.rb
|
|
70
69
|
- lib/omq/engine.rb
|
|
70
|
+
- lib/omq/engine/connection_setup.rb
|
|
71
|
+
- lib/omq/engine/heartbeat.rb
|
|
72
|
+
- lib/omq/engine/reconnect.rb
|
|
73
|
+
- lib/omq/engine/recv_pump.rb
|
|
74
|
+
- lib/omq/monitor_event.rb
|
|
71
75
|
- lib/omq/options.rb
|
|
72
76
|
- lib/omq/pair.rb
|
|
73
|
-
- lib/omq/peer.rb
|
|
74
77
|
- lib/omq/pub_sub.rb
|
|
75
78
|
- lib/omq/push_pull.rb
|
|
76
79
|
- lib/omq/queue_interface.rb
|
|
77
|
-
- lib/omq/radio_dish.rb
|
|
78
80
|
- lib/omq/reactor.rb
|
|
79
81
|
- lib/omq/readable.rb
|
|
80
82
|
- lib/omq/req_rep.rb
|
|
81
83
|
- lib/omq/router_dealer.rb
|
|
82
84
|
- lib/omq/routing.rb
|
|
83
|
-
- lib/omq/routing/
|
|
84
|
-
- lib/omq/routing/client.rb
|
|
85
|
+
- lib/omq/routing/conn_send_pump.rb
|
|
85
86
|
- lib/omq/routing/dealer.rb
|
|
86
|
-
- lib/omq/routing/
|
|
87
|
+
- lib/omq/routing/fair_queue.rb
|
|
88
|
+
- lib/omq/routing/fair_recv.rb
|
|
87
89
|
- lib/omq/routing/fan_out.rb
|
|
88
|
-
- lib/omq/routing/gather.rb
|
|
89
90
|
- lib/omq/routing/pair.rb
|
|
90
|
-
- lib/omq/routing/peer.rb
|
|
91
91
|
- lib/omq/routing/pub.rb
|
|
92
92
|
- lib/omq/routing/pull.rb
|
|
93
93
|
- lib/omq/routing/push.rb
|
|
94
|
-
- lib/omq/routing/radio.rb
|
|
95
94
|
- lib/omq/routing/rep.rb
|
|
96
95
|
- lib/omq/routing/req.rb
|
|
97
96
|
- lib/omq/routing/round_robin.rb
|
|
98
97
|
- lib/omq/routing/router.rb
|
|
99
|
-
- lib/omq/routing/scatter.rb
|
|
100
|
-
- lib/omq/routing/server.rb
|
|
101
98
|
- lib/omq/routing/sub.rb
|
|
102
99
|
- lib/omq/routing/xpub.rb
|
|
103
100
|
- lib/omq/routing/xsub.rb
|
|
104
|
-
- lib/omq/scatter_gather.rb
|
|
105
|
-
- lib/omq/single_frame.rb
|
|
106
101
|
- lib/omq/socket.rb
|
|
107
102
|
- lib/omq/transport/inproc.rb
|
|
103
|
+
- lib/omq/transport/inproc/direct_pipe.rb
|
|
108
104
|
- lib/omq/transport/ipc.rb
|
|
109
105
|
- lib/omq/transport/tcp.rb
|
|
110
|
-
- lib/omq/transport/tls.rb
|
|
111
106
|
- lib/omq/version.rb
|
|
112
107
|
- lib/omq/writable.rb
|
|
113
108
|
homepage: https://github.com/zeromq/omq
|
data/lib/omq/channel.rb
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module OMQ
|
|
4
|
-
class CHANNEL < Socket
|
|
5
|
-
include Readable
|
|
6
|
-
include Writable
|
|
7
|
-
include SingleFrame
|
|
8
|
-
|
|
9
|
-
def initialize(endpoints = nil, linger: 0, backend: nil)
|
|
10
|
-
_init_engine(:CHANNEL, linger: linger, backend: backend)
|
|
11
|
-
_attach(endpoints, default: :connect)
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
end
|
data/lib/omq/client_server.rb
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module OMQ
|
|
4
|
-
class CLIENT < Socket
|
|
5
|
-
include Readable
|
|
6
|
-
include Writable
|
|
7
|
-
include SingleFrame
|
|
8
|
-
|
|
9
|
-
def initialize(endpoints = nil, linger: 0, backend: nil)
|
|
10
|
-
_init_engine(:CLIENT, linger: linger, backend: backend)
|
|
11
|
-
_attach(endpoints, default: :connect)
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
class SERVER < Socket
|
|
16
|
-
include Readable
|
|
17
|
-
include Writable
|
|
18
|
-
include SingleFrame
|
|
19
|
-
|
|
20
|
-
def initialize(endpoints = nil, linger: 0, backend: nil)
|
|
21
|
-
_init_engine(:SERVER, linger: linger, backend: backend)
|
|
22
|
-
_attach(endpoints, default: :bind)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# Sends a message to a specific peer by routing ID.
|
|
26
|
-
#
|
|
27
|
-
# @param routing_id [String] 4-byte routing ID
|
|
28
|
-
# @param message [String] message body
|
|
29
|
-
# @return [self]
|
|
30
|
-
#
|
|
31
|
-
def send_to(routing_id, message)
|
|
32
|
-
parts = [routing_id.b.freeze, message.b.freeze]
|
|
33
|
-
with_timeout(@options.write_timeout) { @engine.enqueue_send(parts) }
|
|
34
|
-
self
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
data/lib/omq/peer.rb
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module OMQ
|
|
4
|
-
class PEER < Socket
|
|
5
|
-
include Readable
|
|
6
|
-
include Writable
|
|
7
|
-
include SingleFrame
|
|
8
|
-
|
|
9
|
-
def initialize(endpoints = nil, linger: 0, backend: nil)
|
|
10
|
-
_init_engine(:PEER, linger: linger, backend: backend)
|
|
11
|
-
_attach(endpoints, default: :connect)
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
# Sends a message to a specific peer by routing ID.
|
|
15
|
-
#
|
|
16
|
-
# @param routing_id [String] 4-byte routing ID
|
|
17
|
-
# @param message [String] message body
|
|
18
|
-
# @return [self]
|
|
19
|
-
#
|
|
20
|
-
def send_to(routing_id, message)
|
|
21
|
-
parts = [routing_id.b.freeze, message.b.freeze]
|
|
22
|
-
with_timeout(@options.write_timeout) { @engine.enqueue_send(parts) }
|
|
23
|
-
self
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
data/lib/omq/radio_dish.rb
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module OMQ
|
|
4
|
-
class RADIO < Socket
|
|
5
|
-
include Writable
|
|
6
|
-
|
|
7
|
-
def initialize(endpoints = nil, linger: 0, conflate: false, backend: nil)
|
|
8
|
-
_init_engine(:RADIO, linger: linger, conflate: conflate, backend: backend)
|
|
9
|
-
_attach(endpoints, default: :bind)
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
# Publishes a message to a group.
|
|
13
|
-
#
|
|
14
|
-
# @param group [String] group name
|
|
15
|
-
# @param body [String] message body
|
|
16
|
-
# @return [self]
|
|
17
|
-
#
|
|
18
|
-
def publish(group, body)
|
|
19
|
-
with_timeout(@options.write_timeout) do
|
|
20
|
-
@engine.enqueue_send([group.b.freeze, body.b.freeze])
|
|
21
|
-
end
|
|
22
|
-
self
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# Sends a message to a group.
|
|
26
|
-
#
|
|
27
|
-
# @param message [String] message body (requires group: kwarg)
|
|
28
|
-
# @param group [String] group name
|
|
29
|
-
# @return [self]
|
|
30
|
-
#
|
|
31
|
-
def send(message, group: nil)
|
|
32
|
-
raise ArgumentError, "RADIO requires a group (use group: kwarg, publish, or << [group, body])" unless group
|
|
33
|
-
publish(group, message)
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# Sends a message to a group via [group, body] array.
|
|
37
|
-
#
|
|
38
|
-
# @param message [Array<String>] [group, body]
|
|
39
|
-
# @return [self]
|
|
40
|
-
#
|
|
41
|
-
def <<(message)
|
|
42
|
-
raise ArgumentError, "RADIO requires [group, body] array" unless message.is_a?(Array) && message.size == 2
|
|
43
|
-
publish(message[0], message[1])
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
class DISH < Socket
|
|
48
|
-
include Readable
|
|
49
|
-
|
|
50
|
-
def initialize(endpoints = nil, linger: 0, group: nil, backend: nil)
|
|
51
|
-
_init_engine(:DISH, linger: linger, backend: backend)
|
|
52
|
-
_attach(endpoints, default: :connect)
|
|
53
|
-
join(group) if group
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
# Joins a group.
|
|
57
|
-
#
|
|
58
|
-
# @param group [String]
|
|
59
|
-
# @return [void]
|
|
60
|
-
#
|
|
61
|
-
def join(group)
|
|
62
|
-
@engine.routing.join(group)
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
# Leaves a group.
|
|
66
|
-
#
|
|
67
|
-
# @param group [String]
|
|
68
|
-
# @return [void]
|
|
69
|
-
#
|
|
70
|
-
def leave(group)
|
|
71
|
-
@engine.routing.leave(group)
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
end
|