omq-cli 0.12.3 → 0.14.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 +118 -0
- data/README.md +20 -12
- data/lib/omq/cli/base_runner.rb +42 -12
- data/lib/omq/cli/cli_parser.rb +51 -50
- data/lib/omq/cli/client_server.rb +5 -7
- data/lib/omq/cli/config.rb +2 -2
- data/lib/omq/cli/expression_evaluator.rb +7 -4
- data/lib/omq/cli/formatter.rb +15 -35
- data/lib/omq/cli/parallel_worker.rb +30 -11
- data/lib/omq/cli/pipe.rb +26 -11
- data/lib/omq/cli/pipe_worker.rb +47 -38
- data/lib/omq/cli/radio_dish.rb +0 -1
- data/lib/omq/cli/router_dealer.rb +1 -2
- data/lib/omq/cli/socket_setup.rb +52 -12
- data/lib/omq/cli/term.rb +36 -22
- data/lib/omq/cli/version.rb +1 -1
- data/lib/omq/cli.rb +1 -3
- metadata +19 -19
|
@@ -29,8 +29,15 @@ module OMQ
|
|
|
29
29
|
compile_expr
|
|
30
30
|
run_loop
|
|
31
31
|
run_end_block
|
|
32
|
-
rescue
|
|
33
|
-
|
|
32
|
+
rescue OMQ::SocketDeadError => error
|
|
33
|
+
# Socket was killed by a protocol violation on the peer side
|
|
34
|
+
# (see Engine#signal_fatal_error). Surface the underlying
|
|
35
|
+
# cause via the log stream and exit cleanly -- the Ractor
|
|
36
|
+
# completes, consumer threads unblock.
|
|
37
|
+
reason = error.cause&.message || error.message
|
|
38
|
+
@log_port.send("omq: #{reason}")
|
|
39
|
+
rescue => error
|
|
40
|
+
@error_port.send("#{error.class}: #{error.message}")
|
|
34
41
|
ensure
|
|
35
42
|
@sock&.close
|
|
36
43
|
end
|
|
@@ -43,6 +50,8 @@ module OMQ
|
|
|
43
50
|
def setup_socket
|
|
44
51
|
@sock = @config.ffi ? OMQ.const_get(@socket_sym).new(backend: :ffi) : OMQ.const_get(@socket_sym).new
|
|
45
52
|
OMQ::CLI::SocketSetup.apply_options(@sock, @config)
|
|
53
|
+
OMQ::CLI::SocketSetup.apply_recv_maxsz(@sock, @config)
|
|
54
|
+
OMQ::CLI::SocketSetup.apply_compression(@sock, @config, @config.type_name)
|
|
46
55
|
@sock.identity = @config.identity if @config.identity
|
|
47
56
|
OMQ::CLI::SocketSetup.attach_endpoints(@sock, @endpoints, verbose: 0)
|
|
48
57
|
end
|
|
@@ -51,20 +60,32 @@ module OMQ
|
|
|
51
60
|
def log_endpoints
|
|
52
61
|
return unless @config.verbose >= 1
|
|
53
62
|
@endpoints.each do |ep|
|
|
54
|
-
@log_port.send(OMQ::CLI::Term.format_attach(ep.bind? ? :bind : :connect, ep.url, @config.
|
|
63
|
+
@log_port.send(OMQ::CLI::Term.format_attach(ep.bind? ? :bind : :connect, ep.url, @config.timestamps))
|
|
55
64
|
end
|
|
56
65
|
end
|
|
57
66
|
|
|
58
67
|
|
|
59
68
|
def start_monitors
|
|
60
|
-
|
|
61
|
-
|
|
69
|
+
trace = @config.verbose >= 3
|
|
70
|
+
log_events = @config.verbose >= 2
|
|
62
71
|
@sock.monitor(verbose: trace) do |event|
|
|
63
|
-
@log_port.send(OMQ::CLI::Term.format_event(event, @config.
|
|
72
|
+
@log_port.send(OMQ::CLI::Term.format_event(event, @config.timestamps)) if log_events
|
|
73
|
+
kill_on_protocol_error(event)
|
|
64
74
|
end
|
|
65
75
|
end
|
|
66
76
|
|
|
67
77
|
|
|
78
|
+
# Mirrors BaseRunner#kill_on_protocol_error: CLI-level policy
|
|
79
|
+
# that protocol-level disconnects kill the socket so the
|
|
80
|
+
# recv loop unblocks with SocketDeadError.
|
|
81
|
+
def kill_on_protocol_error(event)
|
|
82
|
+
return unless event.type == :disconnected
|
|
83
|
+
error = event.detail && event.detail[:error]
|
|
84
|
+
return unless error.is_a?(Protocol::ZMTP::Error)
|
|
85
|
+
@sock.engine.signal_fatal_error(error)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
|
|
68
89
|
def wait_for_peer
|
|
69
90
|
if @config.timeout
|
|
70
91
|
Fiber.scheduler.with_timeout(@config.timeout) do
|
|
@@ -81,7 +102,7 @@ module OMQ
|
|
|
81
102
|
def compile_expr
|
|
82
103
|
@begin_proc, @end_proc, @eval_proc =
|
|
83
104
|
OMQ::CLI::ExpressionEvaluator.compile_inside_ractor(@config.recv_expr)
|
|
84
|
-
@fmt = OMQ::CLI::Formatter.new(@config.format
|
|
105
|
+
@fmt = OMQ::CLI::Formatter.new(@config.format)
|
|
85
106
|
@ctx = Object.new
|
|
86
107
|
@ctx.instance_exec(&@begin_proc) if @begin_proc
|
|
87
108
|
end
|
|
@@ -106,7 +127,6 @@ module OMQ
|
|
|
106
127
|
loop do
|
|
107
128
|
parts = @sock.receive
|
|
108
129
|
break if parts.nil?
|
|
109
|
-
parts = @fmt.decompress(parts)
|
|
110
130
|
if @eval_proc
|
|
111
131
|
parts = normalize(
|
|
112
132
|
@ctx.instance_exec(parts, &@eval_proc)
|
|
@@ -131,10 +151,9 @@ module OMQ
|
|
|
131
151
|
loop do
|
|
132
152
|
parts = @sock.receive
|
|
133
153
|
break if parts.nil?
|
|
134
|
-
parts = @fmt.decompress(parts)
|
|
135
154
|
reply = compute_reply(parts)
|
|
136
155
|
output(reply)
|
|
137
|
-
@sock.send(
|
|
156
|
+
@sock.send(reply)
|
|
138
157
|
i += 1
|
|
139
158
|
break if n && n > 0 && i >= n
|
|
140
159
|
end
|
|
@@ -166,7 +185,7 @@ module OMQ
|
|
|
166
185
|
|
|
167
186
|
|
|
168
187
|
def normalize(result)
|
|
169
|
-
OMQ::CLI::ExpressionEvaluator.normalize_result(result)
|
|
188
|
+
OMQ::CLI::ExpressionEvaluator.normalize_result(result, format: @config.format)
|
|
170
189
|
end
|
|
171
190
|
|
|
172
191
|
|
data/lib/omq/cli/pipe.rb
CHANGED
|
@@ -11,9 +11,8 @@ module OMQ
|
|
|
11
11
|
|
|
12
12
|
# @param config [Config] frozen CLI configuration
|
|
13
13
|
def initialize(config)
|
|
14
|
-
@config
|
|
15
|
-
@
|
|
16
|
-
@fmt_out = Formatter.new(config.format, compress: config.compress_out || config.compress)
|
|
14
|
+
@config = config
|
|
15
|
+
@fmt = Formatter.new(config.format)
|
|
17
16
|
end
|
|
18
17
|
|
|
19
18
|
|
|
@@ -51,12 +50,16 @@ module OMQ
|
|
|
51
50
|
@pull, @push = build_pull_push(in_eps, out_eps)
|
|
52
51
|
compile_expr
|
|
53
52
|
@sock = @pull # for eval instance_exec
|
|
54
|
-
start_event_monitors
|
|
53
|
+
start_event_monitors
|
|
55
54
|
wait_for_peers_with_timeout if config.timeout
|
|
56
55
|
setup_sequential_transient(task)
|
|
57
56
|
@sock.instance_exec(&@recv_begin_proc) if @recv_begin_proc
|
|
58
57
|
sequential_message_loop(fan_out: out_eps.size > 1)
|
|
59
58
|
@sock.instance_exec(&@recv_end_proc) if @recv_end_proc
|
|
59
|
+
rescue OMQ::SocketDeadError => error
|
|
60
|
+
reason = error.cause&.message || error.message
|
|
61
|
+
$stderr.write("omq: #{reason}\n")
|
|
62
|
+
exit 1
|
|
60
63
|
ensure
|
|
61
64
|
@pull&.close
|
|
62
65
|
@push&.close
|
|
@@ -85,8 +88,11 @@ module OMQ
|
|
|
85
88
|
push = OMQ::PUSH.new(**kwargs)
|
|
86
89
|
SocketSetup.apply_options(pull, config)
|
|
87
90
|
SocketSetup.apply_options(push, config)
|
|
88
|
-
SocketSetup.
|
|
89
|
-
SocketSetup.
|
|
91
|
+
SocketSetup.apply_recv_maxsz(pull, config)
|
|
92
|
+
SocketSetup.apply_compression(pull, config, "pull")
|
|
93
|
+
SocketSetup.apply_compression(push, config, "push")
|
|
94
|
+
SocketSetup.attach_endpoints(pull, in_eps, verbose: config.verbose, timestamps: config.timestamps)
|
|
95
|
+
SocketSetup.attach_endpoints(push, out_eps, verbose: config.verbose, timestamps: config.timestamps)
|
|
90
96
|
[pull, push]
|
|
91
97
|
end
|
|
92
98
|
|
|
@@ -107,10 +113,9 @@ module OMQ
|
|
|
107
113
|
loop do
|
|
108
114
|
parts = @pull.receive
|
|
109
115
|
break if parts.nil?
|
|
110
|
-
parts = @fmt_in.decompress(parts)
|
|
111
116
|
parts = eval_recv_expr(parts)
|
|
112
117
|
if parts && !parts.empty?
|
|
113
|
-
@push.send(
|
|
118
|
+
@push.send(parts)
|
|
114
119
|
end
|
|
115
120
|
# Yield after send so send-pump fibers can drain the queue
|
|
116
121
|
# before the next message is enqueued. Without this, one pump
|
|
@@ -163,7 +168,7 @@ module OMQ
|
|
|
163
168
|
def set_pipe_process_title
|
|
164
169
|
in_eps, out_eps = resolve_endpoints
|
|
165
170
|
title = ["omq pipe"]
|
|
166
|
-
title << "-z" if config.compress
|
|
171
|
+
title << "-z" if config.compress
|
|
167
172
|
title << "-P#{config.parallel}" if config.parallel
|
|
168
173
|
title.concat(in_eps.map(&:url))
|
|
169
174
|
title << "->"
|
|
@@ -193,13 +198,23 @@ module OMQ
|
|
|
193
198
|
|
|
194
199
|
|
|
195
200
|
def start_event_monitors
|
|
196
|
-
trace
|
|
201
|
+
trace = config.verbose >= 3
|
|
202
|
+
log_events = config.verbose >= 2
|
|
197
203
|
[@pull, @push].each do |sock|
|
|
198
204
|
sock.monitor(verbose: trace) do |event|
|
|
199
|
-
Term.write_event(event, config.
|
|
205
|
+
Term.write_event(event, config.timestamps) if log_events
|
|
206
|
+
kill_on_protocol_error(sock, event)
|
|
200
207
|
end
|
|
201
208
|
end
|
|
202
209
|
end
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def kill_on_protocol_error(sock, event)
|
|
213
|
+
return unless event.type == :disconnected
|
|
214
|
+
error = event.detail && event.detail[:error]
|
|
215
|
+
return unless error.is_a?(Protocol::ZMTP::Error)
|
|
216
|
+
sock.engine.signal_fatal_error(error)
|
|
217
|
+
end
|
|
203
218
|
end
|
|
204
219
|
end
|
|
205
220
|
end
|
data/lib/omq/cli/pipe_worker.rb
CHANGED
|
@@ -19,13 +19,14 @@ module OMQ
|
|
|
19
19
|
Async do
|
|
20
20
|
setup_sockets
|
|
21
21
|
log_endpoints if @config.verbose >= 1
|
|
22
|
-
start_monitors
|
|
22
|
+
start_monitors
|
|
23
23
|
wait_for_peers_with_timeout if @config.timeout
|
|
24
24
|
compile_expr
|
|
25
25
|
run_message_loop
|
|
26
26
|
run_end_block
|
|
27
|
-
rescue OMQ::
|
|
28
|
-
|
|
27
|
+
rescue OMQ::SocketDeadError => error
|
|
28
|
+
reason = error.cause&.message || error.message
|
|
29
|
+
@log_port.send("omq: #{reason}")
|
|
29
30
|
ensure
|
|
30
31
|
@pull&.close
|
|
31
32
|
@push&.close
|
|
@@ -42,6 +43,9 @@ module OMQ
|
|
|
42
43
|
@push = OMQ::PUSH.new(**kwargs)
|
|
43
44
|
OMQ::CLI::SocketSetup.apply_options(@pull, @config)
|
|
44
45
|
OMQ::CLI::SocketSetup.apply_options(@push, @config)
|
|
46
|
+
OMQ::CLI::SocketSetup.apply_recv_maxsz(@pull, @config)
|
|
47
|
+
OMQ::CLI::SocketSetup.apply_compression(@pull, @config, "pull")
|
|
48
|
+
OMQ::CLI::SocketSetup.apply_compression(@push, @config, "push")
|
|
45
49
|
OMQ::CLI::SocketSetup.attach_endpoints(@pull, @in_eps, verbose: 0)
|
|
46
50
|
OMQ::CLI::SocketSetup.attach_endpoints(@push, @out_eps, verbose: 0)
|
|
47
51
|
end
|
|
@@ -49,21 +53,31 @@ module OMQ
|
|
|
49
53
|
|
|
50
54
|
def log_endpoints
|
|
51
55
|
(@in_eps + @out_eps).each do |ep|
|
|
52
|
-
@log_port.send(OMQ::CLI::Term.format_attach(ep.bind? ? :bind : :connect, ep.url, @config.
|
|
56
|
+
@log_port.send(OMQ::CLI::Term.format_attach(ep.bind? ? :bind : :connect, ep.url, @config.timestamps))
|
|
53
57
|
end
|
|
54
58
|
end
|
|
55
59
|
|
|
56
60
|
|
|
57
61
|
def start_monitors
|
|
58
|
-
trace
|
|
62
|
+
trace = @config.verbose >= 3
|
|
63
|
+
log_events = @config.verbose >= 2
|
|
59
64
|
[@pull, @push].each do |sock|
|
|
60
65
|
sock.monitor(verbose: trace) do |event|
|
|
61
|
-
@log_port.send(OMQ::CLI::Term.format_event(event, @config.
|
|
66
|
+
@log_port.send(OMQ::CLI::Term.format_event(event, @config.timestamps)) if log_events
|
|
67
|
+
kill_on_protocol_error(sock, event)
|
|
62
68
|
end
|
|
63
69
|
end
|
|
64
70
|
end
|
|
65
71
|
|
|
66
72
|
|
|
73
|
+
def kill_on_protocol_error(sock, event)
|
|
74
|
+
return unless event.type == :disconnected
|
|
75
|
+
error = event.detail && event.detail[:error]
|
|
76
|
+
return unless error.is_a?(Protocol::ZMTP::Error)
|
|
77
|
+
sock.engine.signal_fatal_error(error)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
|
|
67
81
|
# With --timeout set, fail fast if peers never show up. Without
|
|
68
82
|
# it, there's no point waiting: PULL#receive blocks naturally
|
|
69
83
|
# and PUSH buffers up to send_hwm when no peer is present.
|
|
@@ -80,8 +94,7 @@ module OMQ
|
|
|
80
94
|
def compile_expr
|
|
81
95
|
@begin_proc, @end_proc, @eval_proc =
|
|
82
96
|
OMQ::CLI::ExpressionEvaluator.compile_inside_ractor(@config.recv_expr)
|
|
83
|
-
@
|
|
84
|
-
@fmt_out = OMQ::CLI::Formatter.new(@config.format, compress: @config.compress_out || @config.compress)
|
|
97
|
+
@fmt = OMQ::CLI::Formatter.new(@config.format)
|
|
85
98
|
@ctx = Object.new
|
|
86
99
|
@ctx.instance_exec(&@begin_proc) if @begin_proc
|
|
87
100
|
end
|
|
@@ -91,39 +104,15 @@ module OMQ
|
|
|
91
104
|
n = @config.count
|
|
92
105
|
if @eval_proc
|
|
93
106
|
if n && n > 0
|
|
94
|
-
n.times
|
|
95
|
-
parts = @pull.receive
|
|
96
|
-
break if parts.nil?
|
|
97
|
-
parts = OMQ::CLI::ExpressionEvaluator.normalize_result(
|
|
98
|
-
@ctx.instance_exec(@fmt_in.decompress(parts), &@eval_proc)
|
|
99
|
-
)
|
|
100
|
-
next if parts.nil?
|
|
101
|
-
@push << @fmt_out.compress(parts) unless parts.empty?
|
|
102
|
-
end
|
|
107
|
+
n.times { break unless process_one_eval }
|
|
103
108
|
else
|
|
104
|
-
loop
|
|
105
|
-
parts = @pull.receive
|
|
106
|
-
break if parts.nil?
|
|
107
|
-
parts = OMQ::CLI::ExpressionEvaluator.normalize_result(
|
|
108
|
-
@ctx.instance_exec(@fmt_in.decompress(parts), &@eval_proc)
|
|
109
|
-
)
|
|
110
|
-
next if parts.nil?
|
|
111
|
-
@push << @fmt_out.compress(parts) unless parts.empty?
|
|
112
|
-
end
|
|
109
|
+
loop { break unless process_one_eval }
|
|
113
110
|
end
|
|
114
111
|
else
|
|
115
112
|
if n && n > 0
|
|
116
|
-
n.times
|
|
117
|
-
parts = @pull.receive
|
|
118
|
-
break if parts.nil?
|
|
119
|
-
@push << @fmt_out.compress(@fmt_in.decompress(parts))
|
|
120
|
-
end
|
|
113
|
+
n.times { break unless process_one_passthrough }
|
|
121
114
|
else
|
|
122
|
-
loop
|
|
123
|
-
parts = @pull.receive
|
|
124
|
-
break if parts.nil?
|
|
125
|
-
@push << @fmt_out.compress(@fmt_in.decompress(parts))
|
|
126
|
-
end
|
|
115
|
+
loop { break unless process_one_passthrough }
|
|
127
116
|
end
|
|
128
117
|
end
|
|
129
118
|
rescue IO::TimeoutError, Async::TimeoutError
|
|
@@ -131,12 +120,32 @@ module OMQ
|
|
|
131
120
|
end
|
|
132
121
|
|
|
133
122
|
|
|
123
|
+
def process_one_eval
|
|
124
|
+
parts_in = @pull.receive
|
|
125
|
+
return false if parts_in.nil?
|
|
126
|
+
parts_out = OMQ::CLI::ExpressionEvaluator.normalize_result(
|
|
127
|
+
@ctx.instance_exec(parts_in, &@eval_proc), format: @config.format
|
|
128
|
+
)
|
|
129
|
+
return true if parts_out.nil? || parts_out.empty?
|
|
130
|
+
@push << parts_out
|
|
131
|
+
true
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def process_one_passthrough
|
|
136
|
+
parts_in = @pull.receive
|
|
137
|
+
return false if parts_in.nil?
|
|
138
|
+
@push << parts_in
|
|
139
|
+
true
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
|
|
134
143
|
def run_end_block
|
|
135
144
|
return unless @end_proc
|
|
136
145
|
out = OMQ::CLI::ExpressionEvaluator.normalize_result(
|
|
137
|
-
@ctx.instance_exec(&@end_proc)
|
|
146
|
+
@ctx.instance_exec(&@end_proc), format: @config.format
|
|
138
147
|
)
|
|
139
|
-
@push <<
|
|
148
|
+
@push << out if out && !out.empty?
|
|
140
149
|
end
|
|
141
150
|
end
|
|
142
151
|
end
|
data/lib/omq/cli/radio_dish.rb
CHANGED
|
@@ -25,7 +25,6 @@ module OMQ
|
|
|
25
25
|
break if parts.nil?
|
|
26
26
|
identity = parts.shift
|
|
27
27
|
parts.shift if parts.first == ""
|
|
28
|
-
parts = @fmt.decompress(parts)
|
|
29
28
|
result = eval_recv_expr([display_routing_id(identity), *parts])
|
|
30
29
|
output(result)
|
|
31
30
|
i += 1
|
|
@@ -36,7 +35,7 @@ module OMQ
|
|
|
36
35
|
|
|
37
36
|
|
|
38
37
|
def send_to_peer(id, parts)
|
|
39
|
-
@sock.send([id, "",
|
|
38
|
+
@sock.send([id, "", *parts])
|
|
40
39
|
end
|
|
41
40
|
end
|
|
42
41
|
end
|
data/lib/omq/cli/socket_setup.rb
CHANGED
|
@@ -22,6 +22,40 @@ module OMQ
|
|
|
22
22
|
# it entirely with --recv-maxsz 0.
|
|
23
23
|
DEFAULT_RECV_MAXSZ = 1 << 20
|
|
24
24
|
|
|
25
|
+
# Socket types that never receive application data. These opt
|
|
26
|
+
# out of the default passive-compression behavior -- they would
|
|
27
|
+
# otherwise advertise a profile and wrap every outgoing frame in
|
|
28
|
+
# a 4-byte uncompressed sentinel for no benefit, since there's
|
|
29
|
+
# nothing to decompress in return.
|
|
30
|
+
PURE_SEND_TYPES = %w[push pub scatter radio].freeze
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
# Installs ZMTP-Zstd compression on +sock+ based on +type_name+
|
|
34
|
+
# and the explicit flags in +config+. Three outcomes:
|
|
35
|
+
#
|
|
36
|
+
# * +config.compress+ is true --> active compression (auto-dict).
|
|
37
|
+
# Outgoing frames are compressed; incoming are decoded.
|
|
38
|
+
# * +config.compress+ is false and +type_name+ can receive -->
|
|
39
|
+
# passive compression (RFC Sec. 6.4). The socket advertises the
|
|
40
|
+
# profile so an active peer can compress on the wire and we can
|
|
41
|
+
# decode it, but we never compress our own outgoing frames.
|
|
42
|
+
# * +config.compress+ is false and +type_name+ is in
|
|
43
|
+
# +PURE_SEND_TYPES+ --> no compression. Pure senders have no
|
|
44
|
+
# incoming traffic to decompress, so passive mode is pure
|
|
45
|
+
# overhead on outgoing.
|
|
46
|
+
#
|
|
47
|
+
# Callers pass +type_name+ explicitly (rather than reading it off
|
|
48
|
+
# +config+) so the pipe runners can install different modes on
|
|
49
|
+
# their push/pull ends of a single pipe.
|
|
50
|
+
def self.apply_compression(sock, config, type_name)
|
|
51
|
+
if config.compress
|
|
52
|
+
sock.compression = OMQ::RFC::Zstd::Compression.auto(level: config.compress_level || -3)
|
|
53
|
+
elsif !PURE_SEND_TYPES.include?(type_name)
|
|
54
|
+
sock.compression = OMQ::RFC::Zstd::Compression.auto(passive: true)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
|
|
25
59
|
# Apply common socket options from +config+ to +sock+.
|
|
26
60
|
#
|
|
27
61
|
def self.apply_options(sock, config)
|
|
@@ -44,46 +78,52 @@ module OMQ
|
|
|
44
78
|
sock = config.ffi ? klass.new(backend: :ffi) : klass.new
|
|
45
79
|
sock.conflate = true if config.conflate && %w[pub radio].include?(config.type_name)
|
|
46
80
|
apply_options(sock, config)
|
|
47
|
-
|
|
81
|
+
apply_recv_maxsz(sock, config)
|
|
82
|
+
sock.identity = config.identity if config.identity
|
|
83
|
+
sock.router_mandatory = true if config.type_name == "router"
|
|
84
|
+
apply_compression(sock, config, config.type_name)
|
|
85
|
+
sock
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
# --recv-maxsz: nil → 1 MiB default; 0 → explicitly unlimited; else → as-is.
|
|
90
|
+
def self.apply_recv_maxsz(sock, config)
|
|
48
91
|
sock.max_message_size =
|
|
49
92
|
case config.recv_maxsz
|
|
50
93
|
when nil then DEFAULT_RECV_MAXSZ
|
|
51
94
|
when 0 then nil
|
|
52
95
|
else config.recv_maxsz
|
|
53
96
|
end
|
|
54
|
-
sock.identity = config.identity if config.identity
|
|
55
|
-
sock.router_mandatory = true if config.type_name == "router"
|
|
56
|
-
sock
|
|
57
97
|
end
|
|
58
98
|
|
|
59
99
|
|
|
60
100
|
# Bind/connect +sock+ using URL strings from +config.binds+ / +config.connects+.
|
|
61
|
-
# +verbose+
|
|
101
|
+
# +verbose+ gates logging (>= 1), +timestamps+ controls prefix.
|
|
62
102
|
#
|
|
63
|
-
def self.attach(sock, config, verbose: 0)
|
|
103
|
+
def self.attach(sock, config, verbose: 0, timestamps: nil)
|
|
64
104
|
config.binds.each do |url|
|
|
65
105
|
sock.bind(url)
|
|
66
|
-
CLI::Term.write_attach(:bind, sock.last_endpoint,
|
|
106
|
+
CLI::Term.write_attach(:bind, sock.last_endpoint, timestamps) if verbose >= 1
|
|
67
107
|
end
|
|
68
108
|
config.connects.each do |url|
|
|
69
109
|
sock.connect(url)
|
|
70
|
-
CLI::Term.write_attach(:connect, url,
|
|
110
|
+
CLI::Term.write_attach(:connect, url, timestamps) if verbose >= 1
|
|
71
111
|
end
|
|
72
112
|
end
|
|
73
113
|
|
|
74
114
|
|
|
75
115
|
# Bind/connect +sock+ from an Array of Endpoint objects.
|
|
76
116
|
# Used by PipeRunner, which works with structured endpoint lists.
|
|
77
|
-
# +verbose+
|
|
117
|
+
# +verbose+ gates logging (>= 1), +timestamps+ controls prefix.
|
|
78
118
|
#
|
|
79
|
-
def self.attach_endpoints(sock, endpoints, verbose: 0)
|
|
119
|
+
def self.attach_endpoints(sock, endpoints, verbose: 0, timestamps: nil)
|
|
80
120
|
endpoints.each do |ep|
|
|
81
121
|
if ep.bind?
|
|
82
122
|
sock.bind(ep.url)
|
|
83
|
-
CLI::Term.write_attach(:bind, sock.last_endpoint,
|
|
123
|
+
CLI::Term.write_attach(:bind, sock.last_endpoint, timestamps) if verbose >= 1
|
|
84
124
|
else
|
|
85
125
|
sock.connect(ep.url)
|
|
86
|
-
CLI::Term.write_attach(:connect, ep.url,
|
|
126
|
+
CLI::Term.write_attach(:connect, ep.url, timestamps) if verbose >= 1
|
|
87
127
|
end
|
|
88
128
|
end
|
|
89
129
|
end
|
data/lib/omq/cli/term.rb
CHANGED
|
@@ -15,15 +15,18 @@ module OMQ
|
|
|
15
15
|
module_function
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
# Returns a stderr log line prefix
|
|
19
|
-
#
|
|
20
|
-
# time-correlatable. Otherwise returns the empty string.
|
|
18
|
+
# Returns a stderr log line prefix with a UTC ISO8601 timestamp
|
|
19
|
+
# at the requested precision (:s/:ms/:us), or "" when nil.
|
|
21
20
|
#
|
|
22
|
-
# @param
|
|
21
|
+
# @param timestamps [Symbol, nil] :s, :ms, :us, or nil (disabled)
|
|
23
22
|
# @return [String]
|
|
24
|
-
def log_prefix(
|
|
25
|
-
|
|
26
|
-
"
|
|
23
|
+
def log_prefix(timestamps)
|
|
24
|
+
case timestamps
|
|
25
|
+
when nil then ""
|
|
26
|
+
when :s then "#{Time.now.utc.strftime("%FT%T")}Z "
|
|
27
|
+
when :ms then "#{Time.now.utc.strftime("%FT%T.%3N")}Z "
|
|
28
|
+
when :us then "#{Time.now.utc.strftime("%FT%T.%6N")}Z "
|
|
29
|
+
end
|
|
27
30
|
end
|
|
28
31
|
|
|
29
32
|
|
|
@@ -31,18 +34,29 @@ module OMQ
|
|
|
31
34
|
# trailing newline).
|
|
32
35
|
#
|
|
33
36
|
# @param event [OMQ::MonitorEvent]
|
|
34
|
-
# @param
|
|
37
|
+
# @param timestamps [Symbol, nil]
|
|
35
38
|
# @return [String]
|
|
36
|
-
def format_event(event,
|
|
37
|
-
prefix = log_prefix(
|
|
39
|
+
def format_event(event, timestamps)
|
|
40
|
+
prefix = log_prefix(timestamps)
|
|
38
41
|
case event.type
|
|
39
42
|
when :message_sent
|
|
40
|
-
"#{prefix}omq: >> #{Formatter.preview(event.detail[:parts])}"
|
|
43
|
+
"#{prefix}omq: >> #{Formatter.preview(event.detail[:parts], wire_size: event.detail[:wire_size])}"
|
|
41
44
|
when :message_received
|
|
42
|
-
"#{prefix}omq: << #{Formatter.preview(event.detail[:parts])}"
|
|
45
|
+
"#{prefix}omq: << #{Formatter.preview(event.detail[:parts], wire_size: event.detail[:wire_size])}"
|
|
46
|
+
when :zdict_sent
|
|
47
|
+
"#{prefix}omq: >> ZDICT (#{event.detail[:size]}B)"
|
|
48
|
+
when :zdict_received
|
|
49
|
+
"#{prefix}omq: << ZDICT (#{event.detail[:size]}B)"
|
|
43
50
|
else
|
|
44
51
|
ep = event.endpoint ? " #{event.endpoint}" : ""
|
|
45
|
-
detail =
|
|
52
|
+
detail =
|
|
53
|
+
if event.detail.is_a?(Hash) && event.detail[:reason]
|
|
54
|
+
" (#{event.detail[:reason]})"
|
|
55
|
+
elsif event.detail
|
|
56
|
+
" #{event.detail}"
|
|
57
|
+
else
|
|
58
|
+
""
|
|
59
|
+
end
|
|
46
60
|
"#{prefix}omq: #{event.type}#{ep}#{detail}"
|
|
47
61
|
end
|
|
48
62
|
end
|
|
@@ -52,22 +66,22 @@ module OMQ
|
|
|
52
66
|
#
|
|
53
67
|
# @param kind [:bind, :connect]
|
|
54
68
|
# @param url [String]
|
|
55
|
-
# @param
|
|
69
|
+
# @param timestamps [Symbol, nil]
|
|
56
70
|
# @return [String]
|
|
57
|
-
def format_attach(kind, url,
|
|
71
|
+
def format_attach(kind, url, timestamps)
|
|
58
72
|
verb = kind == :bind ? "Bound to" : "Connecting to"
|
|
59
|
-
"#{log_prefix(
|
|
73
|
+
"#{log_prefix(timestamps)}omq: #{verb} #{url}"
|
|
60
74
|
end
|
|
61
75
|
|
|
62
76
|
|
|
63
77
|
# Writes one formatted event line to +io+ (default $stderr).
|
|
64
78
|
#
|
|
65
79
|
# @param event [OMQ::MonitorEvent]
|
|
66
|
-
# @param
|
|
80
|
+
# @param timestamps [Symbol, nil]
|
|
67
81
|
# @param io [#write] writable sink, default $stderr
|
|
68
82
|
# @return [void]
|
|
69
|
-
def write_event(event,
|
|
70
|
-
io.write("#{format_event(event,
|
|
83
|
+
def write_event(event, timestamps, io: $stderr)
|
|
84
|
+
io.write("#{format_event(event, timestamps)}\n")
|
|
71
85
|
end
|
|
72
86
|
|
|
73
87
|
|
|
@@ -76,11 +90,11 @@ module OMQ
|
|
|
76
90
|
#
|
|
77
91
|
# @param kind [:bind, :connect]
|
|
78
92
|
# @param url [String]
|
|
79
|
-
# @param
|
|
93
|
+
# @param timestamps [Symbol, nil]
|
|
80
94
|
# @param io [#write]
|
|
81
95
|
# @return [void]
|
|
82
|
-
def write_attach(kind, url,
|
|
83
|
-
io.write("#{format_attach(kind, url,
|
|
96
|
+
def write_attach(kind, url, timestamps, io: $stderr)
|
|
97
|
+
io.write("#{format_attach(kind, url, timestamps)}\n")
|
|
84
98
|
end
|
|
85
99
|
end
|
|
86
100
|
end
|
data/lib/omq/cli/version.rb
CHANGED
data/lib/omq/cli.rb
CHANGED
|
@@ -197,6 +197,7 @@ module OMQ
|
|
|
197
197
|
require "omq/rfc/scattergather"
|
|
198
198
|
require "omq/rfc/channel"
|
|
199
199
|
require "omq/rfc/p2p"
|
|
200
|
+
require "omq/rfc/zstd"
|
|
200
201
|
require "async"
|
|
201
202
|
require "json"
|
|
202
203
|
require "console"
|
|
@@ -247,9 +248,6 @@ module OMQ
|
|
|
247
248
|
runner_class.new(config)
|
|
248
249
|
end
|
|
249
250
|
runner.call(task)
|
|
250
|
-
rescue DecompressError => e
|
|
251
|
-
$stderr.puts "omq: #{e.message}"
|
|
252
|
-
exit 1
|
|
253
251
|
rescue IO::TimeoutError, Async::TimeoutError
|
|
254
252
|
$stderr.puts "omq: timeout" unless config.quiet
|
|
255
253
|
exit 2
|