omq-cli 0.14.1 → 0.14.2
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 +41 -0
- data/lib/omq/cli/base_runner.rb +52 -31
- data/lib/omq/cli/expression_evaluator.rb +21 -29
- data/lib/omq/cli/formatter.rb +49 -21
- data/lib/omq/cli/parallel_worker.rb +1 -12
- data/lib/omq/cli/pipe.rb +1 -9
- data/lib/omq/cli/socket_setup.rb +18 -0
- data/lib/omq/cli/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 23eb8d602298e5db1259e6d7d0effe08e8e0dfacba55b8d9a5287800290f2eb9
|
|
4
|
+
data.tar.gz: b492d78fd4997c82434853bc284f7f98c662d905a450e3545c1df2ae822bf40c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a3abd80d9856c52e2674c86a3e31ed4f02d6511cad2e3d9f35a2ab5b65faaf07acdc4c442f3746bc5ed0dd56e730df0fabc4930c0cdfe05ad8e289335fc0e8d4
|
|
7
|
+
data.tar.gz: 98e5cf25c2e267aace41bb958843459ead62da2a338b8a64aa3f6fc3af571dfefaee30b01a0de720b8880a96c6c0c3b55fe7a8439a6b5151a54085233ded3aaa
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,46 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.14.2 — 2026-04-13
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- `kill_on_protocol_error` is now a single
|
|
8
|
+
`SocketSetup.kill_on_protocol_error(sock, event)` class method.
|
|
9
|
+
Previously `BaseRunner`, `ParallelWorker`, and `PipeRunner` each
|
|
10
|
+
carried an identical 4-line copy of the CLI policy that
|
|
11
|
+
protocol-level disconnects mark the socket dead.
|
|
12
|
+
- `ExpressionEvaluator.extract_block` is now a single class method
|
|
13
|
+
used by both the instance compile path and the
|
|
14
|
+
`compile_inside_ractor` path. The in-Ractor copy previously lived
|
|
15
|
+
as a local lambda that duplicated the instance
|
|
16
|
+
`extract_block` method.
|
|
17
|
+
- `Formatter#encode` drops one String allocation per message on
|
|
18
|
+
the ascii / quoted / jsonl / marshal paths by mutating the
|
|
19
|
+
fresh `.join` / `JSON.generate` / `.inspect` result with `<<`
|
|
20
|
+
instead of `+ "\n"`.
|
|
21
|
+
- `Formatter.marshal_preview` and `Formatter.frames_preview` (extracted
|
|
22
|
+
from `Formatter.preview` in the `-vvv` marshal trace work) are now
|
|
23
|
+
`private_class_method` — they were only ever meant to be called
|
|
24
|
+
through `Formatter.preview` but ended up on the public class surface.
|
|
25
|
+
- Dropped a redundant unary `+` before `Formatter.sanitize(...)` in
|
|
26
|
+
`marshal_preview`: `sanitize` already returns a fresh mutable String
|
|
27
|
+
via `.tr`, so the `+""` dup was dead weight.
|
|
28
|
+
- **`-vvv` marshal trace headers now show plaintext and wire byte
|
|
29
|
+
sizes.** Previously `<< (marshal) ...` carried no size info; it
|
|
30
|
+
now renders as `(135B marshal) ...` and, when ZMTP-Zstd
|
|
31
|
+
compression is negotiated, `(135B wire=50B marshal) ...` —
|
|
32
|
+
matching the frame-based preview format used by every other
|
|
33
|
+
`-vvv` output.
|
|
34
|
+
Other formats (ascii/quoted/jsonl/msgpack/raw) already showed
|
|
35
|
+
plaintext size via the frame preview; they now also pick up
|
|
36
|
+
`wire=NB` when compression is active, since `wire_size` is
|
|
37
|
+
side-channelled from `:message_sent` / `:message_received`
|
|
38
|
+
monitor events. Send-side `wire_size` is best-effort — the
|
|
39
|
+
engine's send pump emits the compressed byte count
|
|
40
|
+
asynchronously, so the value reflects the most recently
|
|
41
|
+
*completed* send; receive-side is exact.
|
|
42
|
+
- Hot-path optimized.
|
|
43
|
+
|
|
3
44
|
## 0.14.1 — 2026-04-13
|
|
4
45
|
|
|
5
46
|
### Changed
|
data/lib/omq/cli/base_runner.rb
CHANGED
|
@@ -304,9 +304,19 @@ module OMQ
|
|
|
304
304
|
# may write to stdout (e.g. `-e 'p it'`), and we want the
|
|
305
305
|
# trace line to precede any such output so the sequence on the
|
|
306
306
|
# terminal reads as: trace → eval side-effects → body.
|
|
307
|
+
#
|
|
308
|
+
# +@last_recv_wire_size+ is populated by the :message_received
|
|
309
|
+
# monitor event, which fires *before* the recv queue enqueue
|
|
310
|
+
# (recv_pump.rb) — so by the time @sock.receive returns here,
|
|
311
|
+
# the cache reflects this message. +@last_recv_uncompressed+
|
|
312
|
+
# is captured in #recv_msg from the raw marshal frame size.
|
|
307
313
|
def trace_recv(parts)
|
|
308
314
|
return unless config.verbose >= 3
|
|
309
|
-
|
|
315
|
+
preview = Formatter.preview(parts,
|
|
316
|
+
format: config.format,
|
|
317
|
+
wire_size: @last_recv_wire_size,
|
|
318
|
+
uncompressed_size: @last_recv_uncompressed)
|
|
319
|
+
$stderr.write("#{Term.log_prefix(config.timestamps)}omq: << #{preview}\n")
|
|
310
320
|
$stderr.flush
|
|
311
321
|
end
|
|
312
322
|
|
|
@@ -331,8 +341,9 @@ module OMQ
|
|
|
331
341
|
def send_msg(parts)
|
|
332
342
|
case config.format
|
|
333
343
|
when :marshal
|
|
334
|
-
|
|
335
|
-
|
|
344
|
+
dumped = Marshal.dump(parts)
|
|
345
|
+
trace_send(parts, uncompressed_size: dumped.bytesize)
|
|
346
|
+
@sock.send([dumped])
|
|
336
347
|
else
|
|
337
348
|
return if parts.empty?
|
|
338
349
|
trace_send(parts)
|
|
@@ -342,12 +353,21 @@ module OMQ
|
|
|
342
353
|
end
|
|
343
354
|
|
|
344
355
|
|
|
345
|
-
# Symmetric to #trace_recv — log the outgoing message
|
|
346
|
-
# Marshal.dump
|
|
347
|
-
# (`[nil, :foo, "bar"]`) instead of the wire-side dump
|
|
348
|
-
|
|
356
|
+
# Symmetric to #trace_recv — log the outgoing message using the
|
|
357
|
+
# pre-Marshal.dump +parts+, so -M traces show the app-level
|
|
358
|
+
# object (`[nil, :foo, "bar"]`) instead of the wire-side dump
|
|
359
|
+
# bytes. +@last_send_wire_size+ is best-effort: it reflects the
|
|
360
|
+
# *previous* message (populated by the :message_sent monitor
|
|
361
|
+
# event, which fires on a separate fiber after the pump writes),
|
|
362
|
+
# so early sends may show no `wire=` at all. Receive-side tracing
|
|
363
|
+
# is the authoritative path for observing wire bytes.
|
|
364
|
+
def trace_send(parts, uncompressed_size: nil)
|
|
349
365
|
return unless config.verbose >= 3
|
|
350
|
-
|
|
366
|
+
preview = Formatter.preview(parts,
|
|
367
|
+
format: config.format,
|
|
368
|
+
wire_size: @last_send_wire_size,
|
|
369
|
+
uncompressed_size: uncompressed_size)
|
|
370
|
+
$stderr.write("#{Term.log_prefix(config.timestamps)}omq: >> #{preview}\n")
|
|
351
371
|
$stderr.flush
|
|
352
372
|
end
|
|
353
373
|
|
|
@@ -355,7 +375,13 @@ module OMQ
|
|
|
355
375
|
def recv_msg
|
|
356
376
|
parts = @sock.receive
|
|
357
377
|
return nil if parts.nil?
|
|
358
|
-
|
|
378
|
+
|
|
379
|
+
case config.format
|
|
380
|
+
when :marshal
|
|
381
|
+
@last_recv_uncompressed = parts.first.bytesize
|
|
382
|
+
parts = Marshal.load(parts.first)
|
|
383
|
+
end
|
|
384
|
+
|
|
359
385
|
transient_ready!
|
|
360
386
|
parts
|
|
361
387
|
end
|
|
@@ -499,37 +525,32 @@ module OMQ
|
|
|
499
525
|
# -vvv also log message sent/received traces
|
|
500
526
|
# --timestamps[=s|ms|us]: prepend UTC timestamps to log lines
|
|
501
527
|
#
|
|
502
|
-
# :message_received and :message_sent are
|
|
503
|
-
#
|
|
504
|
-
#
|
|
528
|
+
# :message_received and :message_sent are not *logged* from the
|
|
529
|
+
# monitor fiber — #trace_recv / #trace_send render them inline
|
|
530
|
+
# on the same fiber as the body write, so trace-then-body
|
|
505
531
|
# ordering is strict on a shared tty. The monitor-fiber path
|
|
506
532
|
# suffered from $stderr/$stdout buffer races and from dumping
|
|
507
533
|
# wire-side bytes (pre-Marshal.load on recv, post-Marshal.dump
|
|
508
|
-
# on send) instead of app-level parts.
|
|
509
|
-
|
|
534
|
+
# on send) instead of app-level parts. We still *observe* these
|
|
535
|
+
# events here to side-channel the compressed wire_size — for
|
|
536
|
+
# :message_received the event fires before the recv queue
|
|
537
|
+
# enqueue (engine/recv_pump.rb), so by the time @sock.receive
|
|
538
|
+
# returns, @last_recv_wire_size reflects the current message.
|
|
510
539
|
def start_event_monitor
|
|
511
540
|
trace = config.verbose >= 3
|
|
512
541
|
log_events = config.verbose >= 2
|
|
513
542
|
@sock.monitor(verbose: trace) do |event|
|
|
514
|
-
|
|
515
|
-
|
|
543
|
+
case event.type
|
|
544
|
+
when :message_received
|
|
545
|
+
@last_recv_wire_size = event.detail[:wire_size]
|
|
546
|
+
when :message_sent
|
|
547
|
+
@last_send_wire_size = event.detail[:wire_size]
|
|
548
|
+
else
|
|
549
|
+
Term.write_event(event, config.timestamps) if log_events
|
|
550
|
+
end
|
|
551
|
+
SocketSetup.kill_on_protocol_error(@sock, event)
|
|
516
552
|
end
|
|
517
553
|
end
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
# omq-cli policy: a peer that commits a protocol-level violation
|
|
521
|
-
# (Protocol::ZMTP::Error — oversized frame, decompression
|
|
522
|
-
# bytebomb, bad framing, …) is almost certainly a
|
|
523
|
-
# misconfiguration the user needs to see. Mark the socket dead
|
|
524
|
-
# so the next receive raises SocketDeadError. The library
|
|
525
|
-
# itself just drops the connection and keeps serving the
|
|
526
|
-
# others; this stricter policy is CLI-only.
|
|
527
|
-
def kill_on_protocol_error(event)
|
|
528
|
-
return unless event.type == :disconnected
|
|
529
|
-
error = event.detail && event.detail[:error]
|
|
530
|
-
return unless error.is_a?(Protocol::ZMTP::Error)
|
|
531
|
-
@sock.engine.signal_fatal_error(error)
|
|
532
|
-
end
|
|
533
554
|
end
|
|
534
555
|
end
|
|
535
556
|
end
|
|
@@ -49,7 +49,7 @@ module OMQ
|
|
|
49
49
|
return result if @format == :marshal
|
|
50
50
|
|
|
51
51
|
result = result.is_a?(Array) ? result : [result]
|
|
52
|
-
result.map
|
|
52
|
+
result.map { |part| part.to_s }
|
|
53
53
|
rescue => e
|
|
54
54
|
$stderr.puts "omq: eval error: #{e.message} (#{e.class})"
|
|
55
55
|
exit 3
|
|
@@ -67,7 +67,7 @@ module OMQ
|
|
|
67
67
|
return nil if result.nil?
|
|
68
68
|
return result if format == :marshal
|
|
69
69
|
result = result.is_a?(Array) ? result : [result]
|
|
70
|
-
result.map
|
|
70
|
+
result.map { |part| part.to_s }
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
|
|
@@ -79,22 +79,8 @@ module OMQ
|
|
|
79
79
|
def self.compile_inside_ractor(src)
|
|
80
80
|
return [nil, nil, nil] unless src
|
|
81
81
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
return [expr, nil] unless s
|
|
85
|
-
ci = expr.index("{", s)
|
|
86
|
-
depth = 1
|
|
87
|
-
j = ci + 1
|
|
88
|
-
while j < expr.length && depth > 0
|
|
89
|
-
depth += 1 if expr[j] == "{"
|
|
90
|
-
depth -= 1 if expr[j] == "}"
|
|
91
|
-
j += 1
|
|
92
|
-
end
|
|
93
|
-
[expr[0...s] + expr[j..], expr[(ci + 1)..(j - 2)]]
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
expr, begin_body = extract.(src, "BEGIN")
|
|
97
|
-
expr, end_body = extract.(expr, "END")
|
|
82
|
+
expr, begin_body = extract_block(src, "BEGIN")
|
|
83
|
+
expr, end_body = extract_block(expr, "END")
|
|
98
84
|
|
|
99
85
|
begin_proc = eval("proc { #{begin_body} }") if begin_body
|
|
100
86
|
end_proc = eval("proc { #{end_body} }") if end_body
|
|
@@ -107,17 +93,13 @@ module OMQ
|
|
|
107
93
|
end
|
|
108
94
|
|
|
109
95
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
def extract_block(expr, keyword)
|
|
96
|
+
# Strips a +BEGIN {...}+ or +END {...}+ block from +expr+ and
|
|
97
|
+
# returns +[trimmed_expr, block_body_or_nil]+. Brace-matched scan,
|
|
98
|
+
# so nested `{}` inside the block body are handled. Shared by
|
|
99
|
+
# instance and Ractor compile paths, so must be a class method
|
|
100
|
+
# (Ractors cannot call back into instance state).
|
|
101
|
+
#
|
|
102
|
+
def self.extract_block(expr, keyword)
|
|
121
103
|
start = expr.index(/#{keyword}\s*\{/)
|
|
122
104
|
return [expr, nil] unless start
|
|
123
105
|
|
|
@@ -138,6 +120,16 @@ module OMQ
|
|
|
138
120
|
trimmed = expr[0...start] + expr[j..]
|
|
139
121
|
[trimmed, body]
|
|
140
122
|
end
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
private
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def extract_blocks(expr)
|
|
129
|
+
expr, begin_body = self.class.extract_block(expr, "BEGIN")
|
|
130
|
+
expr, end_body = self.class.extract_block(expr, "END")
|
|
131
|
+
[expr, begin_body, end_body]
|
|
132
|
+
end
|
|
141
133
|
end
|
|
142
134
|
end
|
|
143
135
|
end
|
data/lib/omq/cli/formatter.rb
CHANGED
|
@@ -20,20 +20,20 @@ module OMQ
|
|
|
20
20
|
def encode(parts)
|
|
21
21
|
case @format
|
|
22
22
|
when :ascii
|
|
23
|
-
parts.map { |p| p.b.gsub(/[^[:print:]\t]/, ".") }.join("\t")
|
|
23
|
+
parts.map { |p| p.b.gsub(/[^[:print:]\t]/, ".") }.join("\t") << "\n"
|
|
24
24
|
when :quoted
|
|
25
|
-
parts.map { |p| p.b.dump[1..-2] }.join("\t")
|
|
25
|
+
parts.map { |p| p.b.dump[1..-2] }.join("\t") << "\n"
|
|
26
26
|
when :raw
|
|
27
27
|
parts.each_with_index.map do |p, i|
|
|
28
28
|
Protocol::ZMTP::Codec::Frame.new(p.to_s, more: i < parts.size - 1).to_wire
|
|
29
29
|
end.join
|
|
30
30
|
when :jsonl
|
|
31
|
-
JSON.generate(parts)
|
|
31
|
+
JSON.generate(parts) << "\n"
|
|
32
32
|
when :msgpack
|
|
33
33
|
MessagePack.pack(parts)
|
|
34
34
|
when :marshal
|
|
35
35
|
# Under -M, `parts` is a single Ruby object (not a frame array).
|
|
36
|
-
parts.inspect
|
|
36
|
+
parts.inspect << "\n"
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
39
|
|
|
@@ -103,37 +103,65 @@ module OMQ
|
|
|
103
103
|
# itself (not an Array of frames); the preview inspects it so
|
|
104
104
|
# the reader sees the actual payload structure (e.g.
|
|
105
105
|
# `[nil, :foo, "bar"]`) instead of a meaningless "1obj" header.
|
|
106
|
+
# For marshal, +uncompressed_size+ is the Marshal.dump bytesize
|
|
107
|
+
# (known to the caller, which already serialized for send or
|
|
108
|
+
# received the wire frame for recv) — passed through instead of
|
|
109
|
+
# redumping here.
|
|
106
110
|
#
|
|
107
111
|
# @param parts [Array<String, Object>, Object] message frames, or raw object when +format+ is :marshal
|
|
108
112
|
# @param format [Symbol, nil] active CLI format (:marshal enables object-inspect mode)
|
|
109
113
|
# @param wire_size [Integer, nil] compressed bytes on the wire
|
|
114
|
+
# @param uncompressed_size [Integer, nil] plaintext bytes (marshal only)
|
|
110
115
|
# @return [String] truncated preview of each frame joined by |
|
|
111
|
-
def self.preview(parts, format: nil, wire_size: nil)
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
out << "…" if truncated
|
|
118
|
-
return out
|
|
116
|
+
def self.preview(parts, format: nil, wire_size: nil, uncompressed_size: nil)
|
|
117
|
+
case format
|
|
118
|
+
when :marshal
|
|
119
|
+
marshal_preview(parts, uncompressed_size: uncompressed_size, wire_size: wire_size)
|
|
120
|
+
else
|
|
121
|
+
frames_preview(parts, format: format, wire_size: wire_size)
|
|
119
122
|
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def self.marshal_preview(parts, uncompressed_size:, wire_size:)
|
|
127
|
+
inspected = parts.inspect
|
|
128
|
+
truncated = inspected.bytesize > 60
|
|
129
|
+
inspected = inspected.byteslice(0, 60) if truncated
|
|
130
|
+
body = sanitize(inspected)
|
|
131
|
+
|
|
132
|
+
body << "…" if truncated
|
|
133
|
+
|
|
134
|
+
header = case
|
|
135
|
+
when uncompressed_size && wire_size
|
|
136
|
+
"(#{uncompressed_size}B wire=#{wire_size}B marshal)"
|
|
137
|
+
when uncompressed_size
|
|
138
|
+
"(#{uncompressed_size}B marshal)"
|
|
139
|
+
else
|
|
140
|
+
"(marshal)"
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
"#{header} #{body}"
|
|
144
|
+
end
|
|
145
|
+
private_class_method :marshal_preview
|
|
146
|
+
|
|
120
147
|
|
|
148
|
+
def self.frames_preview(parts, format:, wire_size:)
|
|
121
149
|
nparts = parts.size
|
|
122
150
|
shown = parts.first(3).map { |p| preview_frame(p) }
|
|
123
151
|
tail = nparts > 3 ? "|…" : ""
|
|
124
|
-
total = parts.all?(String) ? parts.sum
|
|
125
|
-
size =
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
end
|
|
152
|
+
total = parts.all?(String) ? parts.sum { |p| p.bytesize } : nil
|
|
153
|
+
size = if wire_size && total
|
|
154
|
+
"#{total}B wire=#{wire_size}B"
|
|
155
|
+
elsif total
|
|
156
|
+
"#{total}B"
|
|
157
|
+
else
|
|
158
|
+
"#{nparts}obj"
|
|
159
|
+
end
|
|
133
160
|
header = nparts > 1 ? "(#{size} #{nparts}F)" : "(#{size})"
|
|
134
161
|
|
|
135
162
|
"#{header} #{shown.join("|")}#{tail}"
|
|
136
163
|
end
|
|
164
|
+
private_class_method :frames_preview
|
|
137
165
|
|
|
138
166
|
|
|
139
167
|
# Renders one frame or decoded object for {Formatter.preview}.
|
|
@@ -70,22 +70,11 @@ module OMQ
|
|
|
70
70
|
log_events = @config.verbose >= 2
|
|
71
71
|
@sock.monitor(verbose: trace) do |event|
|
|
72
72
|
@log_port.send(OMQ::CLI::Term.format_event(event, @config.timestamps)) if log_events
|
|
73
|
-
kill_on_protocol_error(event)
|
|
73
|
+
OMQ::CLI::SocketSetup.kill_on_protocol_error(@sock, event)
|
|
74
74
|
end
|
|
75
75
|
end
|
|
76
76
|
|
|
77
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
|
-
|
|
89
78
|
def wait_for_peer
|
|
90
79
|
if @config.timeout
|
|
91
80
|
Fiber.scheduler.with_timeout(@config.timeout) do
|
data/lib/omq/cli/pipe.rb
CHANGED
|
@@ -203,18 +203,10 @@ module OMQ
|
|
|
203
203
|
[@pull, @push].each do |sock|
|
|
204
204
|
sock.monitor(verbose: trace) do |event|
|
|
205
205
|
Term.write_event(event, config.timestamps) if log_events
|
|
206
|
-
kill_on_protocol_error(sock, event)
|
|
206
|
+
SocketSetup.kill_on_protocol_error(sock, event)
|
|
207
207
|
end
|
|
208
208
|
end
|
|
209
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
|
|
218
210
|
end
|
|
219
211
|
end
|
|
220
212
|
end
|
data/lib/omq/cli/socket_setup.rb
CHANGED
|
@@ -179,6 +179,24 @@ module OMQ
|
|
|
179
179
|
$stderr.puts "OMQ_SERVER_KEY='#{Protocol::ZMTP::Z85.encode(server_pub)}'"
|
|
180
180
|
end
|
|
181
181
|
end
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
# CLI-level policy: a peer that commits a protocol-level violation
|
|
185
|
+
# (Protocol::ZMTP::Error — oversized frame, decompression bytebomb,
|
|
186
|
+
# bad framing, …) is almost certainly a misconfiguration the user
|
|
187
|
+
# needs to see. Mark +sock+ dead so the next receive raises
|
|
188
|
+
# SocketDeadError. The library itself just drops the connection and
|
|
189
|
+
# keeps serving the others; this stricter policy is CLI-only.
|
|
190
|
+
#
|
|
191
|
+
# @param sock [OMQ::Socket]
|
|
192
|
+
# @param event [OMQ::MonitorEvent]
|
|
193
|
+
#
|
|
194
|
+
def self.kill_on_protocol_error(sock, event)
|
|
195
|
+
return unless event.type == :disconnected
|
|
196
|
+
error = event.detail && event.detail[:error]
|
|
197
|
+
return unless error.is_a?(Protocol::ZMTP::Error)
|
|
198
|
+
sock.engine.signal_fatal_error(error)
|
|
199
|
+
end
|
|
182
200
|
end
|
|
183
201
|
end
|
|
184
202
|
end
|
data/lib/omq/cli/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: omq-cli
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.14.
|
|
4
|
+
version: 0.14.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Patrik Wenger
|
|
@@ -18,7 +18,7 @@ dependencies:
|
|
|
18
18
|
version: '0.19'
|
|
19
19
|
- - ">="
|
|
20
20
|
- !ruby/object:Gem::Version
|
|
21
|
-
version: 0.19.
|
|
21
|
+
version: 0.19.3
|
|
22
22
|
type: :runtime
|
|
23
23
|
prerelease: false
|
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -28,7 +28,7 @@ dependencies:
|
|
|
28
28
|
version: '0.19'
|
|
29
29
|
- - ">="
|
|
30
30
|
- !ruby/object:Gem::Version
|
|
31
|
-
version: 0.19.
|
|
31
|
+
version: 0.19.3
|
|
32
32
|
- !ruby/object:Gem::Dependency
|
|
33
33
|
name: omq-ffi
|
|
34
34
|
requirement: !ruby/object:Gem::Requirement
|