omq 0.5.1 → 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 +184 -0
- data/README.md +21 -19
- data/exe/omq +6 -0
- data/lib/omq/cli/base_runner.rb +423 -0
- data/lib/omq/cli/channel.rb +8 -0
- data/lib/omq/cli/client_server.rb +106 -0
- data/lib/omq/cli/config.rb +51 -0
- data/lib/omq/cli/formatter.rb +75 -0
- data/lib/omq/cli/pair.rb +31 -0
- data/lib/omq/cli/peer.rb +8 -0
- data/lib/omq/cli/pipe.rb +249 -0
- data/lib/omq/cli/pub_sub.rb +14 -0
- data/lib/omq/cli/push_pull.rb +14 -0
- data/lib/omq/cli/radio_dish.rb +27 -0
- data/lib/omq/cli/req_rep.rb +77 -0
- data/lib/omq/cli/router_dealer.rb +70 -0
- data/lib/omq/cli/scatter_gather.rb +14 -0
- data/lib/omq/cli.rb +468 -0
- data/lib/omq/pub_sub.rb +2 -2
- data/lib/omq/radio_dish.rb +2 -2
- data/lib/omq/socket.rb +74 -27
- data/lib/omq/version.rb +1 -1
- data/lib/omq/zmtp/connection.rb +24 -3
- data/lib/omq/zmtp/engine.rb +179 -17
- data/lib/omq/zmtp/options.rb +4 -3
- data/lib/omq/zmtp/reactor.rb +10 -5
- data/lib/omq/zmtp/routing/channel.rb +8 -2
- data/lib/omq/zmtp/routing/fan_out.rb +38 -8
- data/lib/omq/zmtp/routing/pair.rb +8 -2
- data/lib/omq/zmtp/routing/peer.rb +7 -1
- data/lib/omq/zmtp/routing/push.rb +14 -7
- data/lib/omq/zmtp/routing/radio.rb +32 -11
- data/lib/omq/zmtp/routing/rep.rb +11 -7
- data/lib/omq/zmtp/routing/req.rb +1 -2
- data/lib/omq/zmtp/routing/round_robin.rb +35 -1
- data/lib/omq/zmtp/routing/router.rb +7 -1
- data/lib/omq/zmtp/routing/scatter.rb +16 -3
- data/lib/omq/zmtp/routing/server.rb +7 -1
- data/lib/omq/zmtp/routing/xsub.rb +7 -1
- data/lib/omq/zmtp/transport/inproc.rb +40 -5
- data/lib/omq/zmtp/transport/ipc.rb +9 -7
- data/lib/omq/zmtp/transport/tcp.rb +14 -7
- data/lib/omq/zmtp/writable.rb +21 -4
- data/lib/omq.rb +7 -0
- metadata +18 -3
- data/exe/omqcat +0 -532
data/lib/omq/socket.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "forwardable"
|
|
4
|
+
|
|
3
5
|
module OMQ
|
|
4
6
|
# Socket base class.
|
|
5
7
|
#
|
|
@@ -8,32 +10,34 @@ module OMQ
|
|
|
8
10
|
#
|
|
9
11
|
attr_reader :options
|
|
10
12
|
|
|
13
|
+
|
|
11
14
|
# @return [Integer, nil] last auto-selected TCP port
|
|
12
15
|
#
|
|
13
16
|
attr_reader :last_tcp_port
|
|
14
17
|
|
|
18
|
+
|
|
15
19
|
# Delegate socket option accessors to @options.
|
|
16
20
|
#
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
21
|
+
extend Forwardable
|
|
22
|
+
|
|
23
|
+
def_delegators :@options,
|
|
24
|
+
:send_hwm, :send_hwm=,
|
|
25
|
+
:recv_hwm, :recv_hwm=,
|
|
26
|
+
:linger, :linger=,
|
|
27
|
+
:identity, :identity=,
|
|
28
|
+
:recv_timeout, :recv_timeout=,
|
|
29
|
+
:send_timeout, :send_timeout=,
|
|
30
|
+
:read_timeout, :read_timeout=,
|
|
31
|
+
:write_timeout, :write_timeout=,
|
|
32
|
+
:router_mandatory, :router_mandatory=,
|
|
33
|
+
:router_mandatory?,
|
|
34
|
+
:reconnect_interval, :reconnect_interval=,
|
|
35
|
+
:heartbeat_interval, :heartbeat_interval=,
|
|
36
|
+
:heartbeat_ttl, :heartbeat_ttl=,
|
|
37
|
+
:heartbeat_timeout, :heartbeat_timeout=,
|
|
38
|
+
:max_message_size, :max_message_size=,
|
|
39
|
+
:mechanism, :mechanism=
|
|
40
|
+
|
|
37
41
|
|
|
38
42
|
# Creates a new socket and binds it to the given endpoint.
|
|
39
43
|
#
|
|
@@ -45,6 +49,7 @@ module OMQ
|
|
|
45
49
|
new(nil, **opts).tap { |s| s.bind(endpoint) }
|
|
46
50
|
end
|
|
47
51
|
|
|
52
|
+
|
|
48
53
|
# Creates a new socket and connects it to the given endpoint.
|
|
49
54
|
#
|
|
50
55
|
# @param endpoint [String]
|
|
@@ -55,8 +60,10 @@ module OMQ
|
|
|
55
60
|
new(nil, **opts).tap { |s| s.connect(endpoint) }
|
|
56
61
|
end
|
|
57
62
|
|
|
63
|
+
|
|
58
64
|
def initialize(endpoints = nil, linger: 0); end
|
|
59
65
|
|
|
66
|
+
|
|
60
67
|
# Binds to an endpoint.
|
|
61
68
|
#
|
|
62
69
|
# @param endpoint [String]
|
|
@@ -67,6 +74,7 @@ module OMQ
|
|
|
67
74
|
@last_tcp_port = @engine.last_tcp_port
|
|
68
75
|
end
|
|
69
76
|
|
|
77
|
+
|
|
70
78
|
# Connects to an endpoint.
|
|
71
79
|
#
|
|
72
80
|
# @param endpoint [String]
|
|
@@ -76,6 +84,7 @@ module OMQ
|
|
|
76
84
|
@engine.connect(endpoint)
|
|
77
85
|
end
|
|
78
86
|
|
|
87
|
+
|
|
79
88
|
# Disconnects from an endpoint.
|
|
80
89
|
#
|
|
81
90
|
# @param endpoint [String]
|
|
@@ -85,6 +94,7 @@ module OMQ
|
|
|
85
94
|
@engine.disconnect(endpoint)
|
|
86
95
|
end
|
|
87
96
|
|
|
97
|
+
|
|
88
98
|
# Unbinds from an endpoint.
|
|
89
99
|
#
|
|
90
100
|
# @param endpoint [String]
|
|
@@ -94,21 +104,52 @@ module OMQ
|
|
|
94
104
|
@engine.unbind(endpoint)
|
|
95
105
|
end
|
|
96
106
|
|
|
107
|
+
|
|
97
108
|
# @return [String, nil] last bound endpoint
|
|
98
109
|
#
|
|
99
110
|
def last_endpoint
|
|
100
111
|
@engine.last_endpoint
|
|
101
112
|
end
|
|
102
113
|
|
|
103
|
-
|
|
114
|
+
|
|
115
|
+
# @return [Async::Promise] resolves when first peer completes handshake
|
|
116
|
+
def peer_connected = @engine.peer_connected
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
# @return [Async::Promise] resolves when first subscriber joins (PUB/XPUB only)
|
|
120
|
+
def subscriber_joined = @engine.routing.subscriber_joined
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
# @return [Async::Promise] resolves when all peers disconnect (after having had peers)
|
|
124
|
+
def all_peers_gone = @engine.all_peers_gone
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
# @return [Integer] current number of peer connections
|
|
128
|
+
def connection_count = @engine.connections.size
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
# Signals end-of-stream on the receive side. A subsequent
|
|
132
|
+
# +#receive+ call that would otherwise block returns +nil+.
|
|
104
133
|
#
|
|
105
|
-
|
|
134
|
+
def close_read
|
|
135
|
+
@engine.dequeue_recv_sentinel
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
# Disable auto-reconnect for connected endpoints.
|
|
140
|
+
def reconnect_enabled=(val)
|
|
141
|
+
@engine.reconnect_enabled = val
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
# Closes the socket.
|
|
106
146
|
#
|
|
107
147
|
def close
|
|
108
148
|
@engine.close
|
|
109
149
|
nil
|
|
110
150
|
end
|
|
111
151
|
|
|
152
|
+
|
|
112
153
|
# Set socket to use unbounded pipes (HWM=0).
|
|
113
154
|
#
|
|
114
155
|
def set_unbounded
|
|
@@ -117,14 +158,17 @@ module OMQ
|
|
|
117
158
|
nil
|
|
118
159
|
end
|
|
119
160
|
|
|
161
|
+
|
|
120
162
|
# @return [String]
|
|
121
163
|
#
|
|
122
164
|
def inspect
|
|
123
165
|
format("#<%s last_endpoint=%p>", self.class, last_endpoint)
|
|
124
166
|
end
|
|
125
167
|
|
|
168
|
+
|
|
126
169
|
private
|
|
127
170
|
|
|
171
|
+
|
|
128
172
|
# Runs a block with a timeout. Uses Async's with_timeout if inside
|
|
129
173
|
# a reactor, otherwise falls back to Timeout.timeout.
|
|
130
174
|
#
|
|
@@ -142,6 +186,7 @@ module OMQ
|
|
|
142
186
|
raise IO::TimeoutError, "timed out"
|
|
143
187
|
end
|
|
144
188
|
|
|
189
|
+
|
|
145
190
|
# Connects or binds based on endpoint prefix convention.
|
|
146
191
|
#
|
|
147
192
|
# @param endpoints [String, nil]
|
|
@@ -159,18 +204,20 @@ module OMQ
|
|
|
159
204
|
end
|
|
160
205
|
end
|
|
161
206
|
|
|
207
|
+
|
|
162
208
|
# Initializes engine and options for a socket type.
|
|
163
209
|
#
|
|
164
210
|
# @param socket_type [Symbol]
|
|
165
211
|
# @param linger [Integer]
|
|
166
212
|
#
|
|
167
213
|
def _init_engine(socket_type, linger:, send_hwm: nil, recv_hwm: nil,
|
|
168
|
-
send_timeout: nil, recv_timeout: nil)
|
|
214
|
+
send_timeout: nil, recv_timeout: nil, conflate: false)
|
|
169
215
|
@options = ZMTP::Options.new(linger: linger)
|
|
170
|
-
@options.send_hwm
|
|
171
|
-
@options.recv_hwm
|
|
172
|
-
@options.send_timeout
|
|
173
|
-
@options.recv_timeout
|
|
216
|
+
@options.send_hwm = send_hwm if send_hwm
|
|
217
|
+
@options.recv_hwm = recv_hwm if recv_hwm
|
|
218
|
+
@options.send_timeout = send_timeout if send_timeout
|
|
219
|
+
@options.recv_timeout = recv_timeout if recv_timeout
|
|
220
|
+
@options.conflate = conflate
|
|
174
221
|
@engine = ZMTP::Engine.new(socket_type, @options)
|
|
175
222
|
end
|
|
176
223
|
end
|
data/lib/omq/version.rb
CHANGED
data/lib/omq/zmtp/connection.rb
CHANGED
|
@@ -13,14 +13,17 @@ module OMQ
|
|
|
13
13
|
#
|
|
14
14
|
attr_reader :peer_socket_type
|
|
15
15
|
|
|
16
|
+
|
|
16
17
|
# @return [String] peer's identity (from READY handshake)
|
|
17
18
|
#
|
|
18
19
|
attr_reader :peer_identity
|
|
19
20
|
|
|
21
|
+
|
|
20
22
|
# @return [Object] transport IO (#read, #write, #close)
|
|
21
23
|
#
|
|
22
24
|
attr_reader :io
|
|
23
25
|
|
|
26
|
+
|
|
24
27
|
# @param io [#read, #write, #close] transport IO
|
|
25
28
|
# @param socket_type [String] our socket type name (e.g. "REQ")
|
|
26
29
|
# @param identity [String] our identity
|
|
@@ -51,6 +54,7 @@ module OMQ
|
|
|
51
54
|
@max_message_size = max_message_size
|
|
52
55
|
end
|
|
53
56
|
|
|
57
|
+
|
|
54
58
|
# Performs the full ZMTP handshake via the configured mechanism.
|
|
55
59
|
#
|
|
56
60
|
# @return [void]
|
|
@@ -77,6 +81,7 @@ module OMQ
|
|
|
77
81
|
end
|
|
78
82
|
end
|
|
79
83
|
|
|
84
|
+
|
|
80
85
|
# Sends a multi-frame message (write + flush).
|
|
81
86
|
#
|
|
82
87
|
# @param parts [Array<String>] message frames
|
|
@@ -89,6 +94,7 @@ module OMQ
|
|
|
89
94
|
end
|
|
90
95
|
end
|
|
91
96
|
|
|
97
|
+
|
|
92
98
|
# Writes a multi-frame message to the buffer without flushing.
|
|
93
99
|
# Call {#flush} after batching writes.
|
|
94
100
|
#
|
|
@@ -101,6 +107,7 @@ module OMQ
|
|
|
101
107
|
end
|
|
102
108
|
end
|
|
103
109
|
|
|
110
|
+
|
|
104
111
|
# Flushes the write buffer to the underlying IO.
|
|
105
112
|
#
|
|
106
113
|
# @return [void]
|
|
@@ -111,6 +118,7 @@ module OMQ
|
|
|
111
118
|
end
|
|
112
119
|
end
|
|
113
120
|
|
|
121
|
+
|
|
114
122
|
# Receives a multi-frame message.
|
|
115
123
|
# PING/PONG commands are handled automatically by #read_frame.
|
|
116
124
|
#
|
|
@@ -125,12 +133,13 @@ module OMQ
|
|
|
125
133
|
yield frame if block_given?
|
|
126
134
|
next
|
|
127
135
|
end
|
|
128
|
-
frames << frame.body
|
|
136
|
+
frames << frame.body.freeze
|
|
129
137
|
break unless frame.more?
|
|
130
138
|
end
|
|
131
|
-
frames
|
|
139
|
+
frames.freeze
|
|
132
140
|
end
|
|
133
141
|
|
|
142
|
+
|
|
134
143
|
# Starts the heartbeat sender task. Call after handshake.
|
|
135
144
|
#
|
|
136
145
|
# @return [#stop, nil] the heartbeat task, or nil if disabled
|
|
@@ -138,7 +147,7 @@ module OMQ
|
|
|
138
147
|
def start_heartbeat
|
|
139
148
|
return nil unless @heartbeat_interval
|
|
140
149
|
@last_received_at = monotonic_now
|
|
141
|
-
@heartbeat_task = Reactor.spawn_pump do
|
|
150
|
+
@heartbeat_task = Reactor.spawn_pump(annotation: "heartbeat") do
|
|
142
151
|
loop do
|
|
143
152
|
sleep @heartbeat_interval
|
|
144
153
|
# Send PING with TTL
|
|
@@ -160,6 +169,7 @@ module OMQ
|
|
|
160
169
|
end
|
|
161
170
|
end
|
|
162
171
|
|
|
172
|
+
|
|
163
173
|
# Sends a command.
|
|
164
174
|
#
|
|
165
175
|
# @param command [Codec::Command]
|
|
@@ -176,6 +186,7 @@ module OMQ
|
|
|
176
186
|
end
|
|
177
187
|
end
|
|
178
188
|
|
|
189
|
+
|
|
179
190
|
# Reads one frame from the wire. Handles PING/PONG automatically.
|
|
180
191
|
# When using an encrypted mechanism, MESSAGE commands are decrypted
|
|
181
192
|
# back to ZMTP frames transparently.
|
|
@@ -215,6 +226,7 @@ module OMQ
|
|
|
215
226
|
end
|
|
216
227
|
end
|
|
217
228
|
|
|
229
|
+
|
|
218
230
|
# Closes the connection.
|
|
219
231
|
#
|
|
220
232
|
# @return [void]
|
|
@@ -226,8 +238,14 @@ module OMQ
|
|
|
226
238
|
# already closed
|
|
227
239
|
end
|
|
228
240
|
|
|
241
|
+
|
|
229
242
|
private
|
|
230
243
|
|
|
244
|
+
|
|
245
|
+
# Writes message parts as ZMTP frames, encrypting if needed.
|
|
246
|
+
#
|
|
247
|
+
# @param parts [Array<String>] message frames
|
|
248
|
+
#
|
|
231
249
|
def write_frames(parts)
|
|
232
250
|
parts.each_with_index do |part, i|
|
|
233
251
|
more = i < parts.size - 1
|
|
@@ -239,14 +257,17 @@ module OMQ
|
|
|
239
257
|
end
|
|
240
258
|
end
|
|
241
259
|
|
|
260
|
+
|
|
242
261
|
def touch_heartbeat
|
|
243
262
|
@last_received_at = monotonic_now if @heartbeat_interval
|
|
244
263
|
end
|
|
245
264
|
|
|
265
|
+
|
|
246
266
|
def monotonic_now
|
|
247
267
|
Async::Clock.now
|
|
248
268
|
end
|
|
249
269
|
|
|
270
|
+
|
|
250
271
|
# Sends one frame to the wire.
|
|
251
272
|
#
|
|
252
273
|
# @param frame [Codec::Frame]
|