omq-cli 0.10.1 → 0.11.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 +44 -0
- data/exe/omq +7 -0
- data/lib/omq/cli/base_runner.rb +4 -13
- data/lib/omq/cli/cli_parser.rb +2 -2
- data/lib/omq/cli/parallel_worker.rb +3 -17
- data/lib/omq/cli/pipe.rb +19 -33
- data/lib/omq/cli/pipe_worker.rb +16 -26
- data/lib/omq/cli/socket_setup.rb +14 -11
- data/lib/omq/cli/term.rb +87 -0
- data/lib/omq/cli/version.rb +1 -1
- data/lib/omq/cli.rb +1 -0
- metadata +4 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1bc589d81fe8cb43e0bef1743ff389b399ad62f5088215772239b05a1992859e
|
|
4
|
+
data.tar.gz: 4c1be278ef64044e2e6f525c5b0ca410d601c3f4711f50f87d2d669a4ab3f3fc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4e50fbd35476b2db4139d16955a8a4249faffe4f1dfe196ee9faea76ab97304dfea9c217066c96dcaabce0b34331338649521f846ce7a7d760e3eefcc0573738
|
|
7
|
+
data.tar.gz: 2f96763515f5fee43718422ef42b0cedaba9f589c389f3a017cd170947ce6e5383d09a142e58d7596532aa382b0ab88b84c5ea6001b796d2a471bf558c520e57
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,49 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.11.0 — 2026-04-10
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **`-vvvv` adds ISO8601 µs-precision timestamps** to every log line
|
|
8
|
+
(endpoint attach, monitor events, message traces). Useful for
|
|
9
|
+
debugging time-sensitive reconnect and handshake races where
|
|
10
|
+
untimestamped `-vvv` output makes every event look instantaneous.
|
|
11
|
+
`-v`/`-vv`/`-vvv` are unchanged.
|
|
12
|
+
|
|
13
|
+
- **YJIT enabled by default in `exe/omq`.** `RubyVM::YJIT.enable` is
|
|
14
|
+
called before loading the CLI. Skipped if `RUBYOPT` is set (so users
|
|
15
|
+
who pass `--disable-yjit` or similar keep their choice), if the
|
|
16
|
+
interpreter lacks YJIT, or if YJIT is already on.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- **Universal default HWM is now 64** (was 100 for most sockets, 16
|
|
21
|
+
for pipe). 64 matches the recv pump's per-fairness-batch limit
|
|
22
|
+
(one batch exactly fills a full queue). Removed the special-case
|
|
23
|
+
`PipeRunner::PIPE_HWM = 16` override — pipe sockets now use the
|
|
24
|
+
same default as everything else, eliminating the documented-but-
|
|
25
|
+
surprising cliff.
|
|
26
|
+
|
|
27
|
+
- **`pipe` no longer waits for peers unless `--timeout` is set.** The
|
|
28
|
+
previous unconditional `Barrier { pull.peer_connected + push.peer_connected }`
|
|
29
|
+
gate served no correctness purpose: `PULL#receive` blocks naturally
|
|
30
|
+
when no source is connected, and `PUSH` buffers up to `send_hwm` when
|
|
31
|
+
no sink is connected, so the loop can start immediately. Concretely,
|
|
32
|
+
`omq pipe -c ipc://@src -b ipc://@sink` started without a sink now
|
|
33
|
+
drains the source until both sides' HWMs are full (recv_queue +
|
|
34
|
+
send_queue = 2 × HWM) instead of silently blocking at 1 × HWM in the
|
|
35
|
+
recv pump while the worker loop sat idle at the wait. When
|
|
36
|
+
`--timeout` *is* set, the wait is preserved as a fail-fast starting
|
|
37
|
+
gate.
|
|
38
|
+
|
|
39
|
+
- **Event formatting consolidated into `OMQ::CLI::Term`** — a new
|
|
40
|
+
stateless module (`module_function`) with `format_attach`,
|
|
41
|
+
`format_event`, `write_attach`, `write_event`, and `log_prefix`.
|
|
42
|
+
Replaces four duplicated copies across `BaseRunner`, `PipeRunner`,
|
|
43
|
+
`ParallelWorker`, and `PipeWorker` that had drifted apart — pipe-
|
|
44
|
+
mode event lines were missing the `-vvvv` timestamp prefix because
|
|
45
|
+
`PipeRunner` had its own copy of the formatter.
|
|
46
|
+
|
|
3
47
|
## 0.10.0 — 2026-04-09
|
|
4
48
|
|
|
5
49
|
### Changed
|
data/exe/omq
CHANGED
|
@@ -2,5 +2,12 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
Warning[:experimental] = false
|
|
4
4
|
|
|
5
|
+
# Enable YJIT by default. Skip if the user set RUBYOPT (they may have
|
|
6
|
+
# --disable-yjit or similar in there), if the interpreter lacks YJIT
|
|
7
|
+
# (TruffleRuby, older MRI), or if it's already on.
|
|
8
|
+
if !ENV["RUBYOPT"] && defined?(RubyVM::YJIT) && !RubyVM::YJIT.enabled?
|
|
9
|
+
RubyVM::YJIT.enable
|
|
10
|
+
end
|
|
11
|
+
|
|
5
12
|
require "omq/cli"
|
|
6
13
|
OMQ::CLI.run
|
data/lib/omq/cli/base_runner.rb
CHANGED
|
@@ -99,7 +99,7 @@ module OMQ
|
|
|
99
99
|
|
|
100
100
|
|
|
101
101
|
def attach_endpoints
|
|
102
|
-
SocketSetup.attach(@sock, config, verbose: config.verbose
|
|
102
|
+
SocketSetup.attach(@sock, config, verbose: config.verbose)
|
|
103
103
|
end
|
|
104
104
|
|
|
105
105
|
|
|
@@ -464,19 +464,10 @@ module OMQ
|
|
|
464
464
|
|
|
465
465
|
# -vv: log connect/disconnect/retry/timeout events via Socket#monitor
|
|
466
466
|
# -vvv: also log message sent/received traces
|
|
467
|
+
# -vvvv: also prepend ISO8601 µs-precision timestamps
|
|
467
468
|
def start_event_monitor
|
|
468
|
-
verbose
|
|
469
|
-
|
|
470
|
-
case event.type
|
|
471
|
-
when :message_sent
|
|
472
|
-
$stderr.write("omq: >> #{Formatter.preview(event.detail[:parts])}\n")
|
|
473
|
-
when :message_received
|
|
474
|
-
$stderr.write("omq: << #{Formatter.preview(event.detail[:parts])}\n")
|
|
475
|
-
else
|
|
476
|
-
ep = event.endpoint ? " #{event.endpoint}" : ""
|
|
477
|
-
detail = event.detail ? " #{event.detail}" : ""
|
|
478
|
-
$stderr.write("omq: #{event.type}#{ep}#{detail}\n")
|
|
479
|
-
end
|
|
469
|
+
@sock.monitor(verbose: config.verbose >= 3) do |event|
|
|
470
|
+
Term.write_event(event, config.verbose)
|
|
480
471
|
end
|
|
481
472
|
end
|
|
482
473
|
end
|
data/lib/omq/cli/cli_parser.rb
CHANGED
|
@@ -340,7 +340,7 @@ module OMQ
|
|
|
340
340
|
}
|
|
341
341
|
o.on("--heartbeat-ivl SECS", Float, "ZMTP heartbeat interval (detects dead peers)") { |v| opts[:heartbeat_ivl] = v }
|
|
342
342
|
o.on("--recv-maxsz SIZE", "Max inbound message size, e.g. 4096, 64K, 1M, 2G (default 1M, 0=unlimited; larger messages drop the connection)") { |v| opts[:recv_maxsz] = parse_byte_size(v) }
|
|
343
|
-
o.on("--hwm N", Integer, "High water mark (default
|
|
343
|
+
o.on("--hwm N", Integer, "High water mark (default 64, 0=unbounded; modal with --in/--out)") do |v|
|
|
344
344
|
case pipe_side
|
|
345
345
|
when :in
|
|
346
346
|
opts[:recv_hwm] = v
|
|
@@ -390,7 +390,7 @@ module OMQ
|
|
|
390
390
|
o.separator " OMQ_CRYPTO (backend: rbnacl or nuckle)"
|
|
391
391
|
|
|
392
392
|
o.separator "\nOther:"
|
|
393
|
-
o.on("-v", "--verbose", "Verbosity: -v endpoints, -vv events, -vvv messages") { opts[:verbose] += 1 }
|
|
393
|
+
o.on("-v", "--verbose", "Verbosity: -v endpoints, -vv events, -vvv messages, -vvvv timestamps") { opts[:verbose] += 1 }
|
|
394
394
|
o.on("-q", "--quiet", "Suppress message output") { opts[:quiet] = true }
|
|
395
395
|
o.on( "--transient", "Exit when all peers disconnect") { opts[:transient] = true }
|
|
396
396
|
o.on( "--ffi", "Use libzmq FFI backend (requires omq-ffi gem + system libzmq 4.x)") do
|
|
@@ -44,14 +44,14 @@ module OMQ
|
|
|
44
44
|
@sock = @config.ffi ? OMQ.const_get(@socket_sym).new(backend: :ffi) : OMQ.const_get(@socket_sym).new
|
|
45
45
|
OMQ::CLI::SocketSetup.apply_options(@sock, @config)
|
|
46
46
|
@sock.identity = @config.identity if @config.identity
|
|
47
|
-
OMQ::CLI::SocketSetup.attach_endpoints(@sock, @endpoints, verbose:
|
|
47
|
+
OMQ::CLI::SocketSetup.attach_endpoints(@sock, @endpoints, verbose: 0)
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
|
|
51
51
|
def log_endpoints
|
|
52
52
|
return unless @config.verbose >= 1
|
|
53
53
|
@endpoints.each do |ep|
|
|
54
|
-
@log_port.send(ep.bind? ?
|
|
54
|
+
@log_port.send(OMQ::CLI::Term.format_attach(ep.bind? ? :bind : :connect, ep.url, @config.verbose))
|
|
55
55
|
end
|
|
56
56
|
end
|
|
57
57
|
|
|
@@ -60,21 +60,7 @@ module OMQ
|
|
|
60
60
|
return unless @config.verbose >= 2
|
|
61
61
|
trace = @config.verbose >= 3
|
|
62
62
|
@sock.monitor(verbose: trace) do |event|
|
|
63
|
-
@log_port.send(format_event(event))
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def format_event(event)
|
|
69
|
-
case event.type
|
|
70
|
-
when :message_sent
|
|
71
|
-
"omq: >> #{OMQ::CLI::Formatter.preview(event.detail[:parts])}"
|
|
72
|
-
when :message_received
|
|
73
|
-
"omq: << #{OMQ::CLI::Formatter.preview(event.detail[:parts])}"
|
|
74
|
-
else
|
|
75
|
-
ep = event.endpoint ? " #{event.endpoint}" : ""
|
|
76
|
-
detail = event.detail ? " #{event.detail}" : ""
|
|
77
|
-
"omq: #{event.type}#{ep}#{detail}"
|
|
63
|
+
@log_port.send(OMQ::CLI::Term.format_event(event, @config.verbose))
|
|
78
64
|
end
|
|
79
65
|
end
|
|
80
66
|
|
data/lib/omq/cli/pipe.rb
CHANGED
|
@@ -5,11 +5,6 @@ module OMQ
|
|
|
5
5
|
# Runner for the virtual "pipe" socket type (PULL -> eval -> PUSH).
|
|
6
6
|
# Supports sequential and parallel (Ractor-based) processing modes.
|
|
7
7
|
class PipeRunner
|
|
8
|
-
# Default HWM for pipe sockets when the user hasn't set one.
|
|
9
|
-
# Much lower than the socket default (1000) to bound memory
|
|
10
|
-
# with large messages in pipeline stages.
|
|
11
|
-
PIPE_HWM = 16
|
|
12
|
-
|
|
13
8
|
# @return [Config] frozen CLI configuration
|
|
14
9
|
attr_reader :config
|
|
15
10
|
|
|
@@ -57,18 +52,7 @@ module OMQ
|
|
|
57
52
|
compile_expr
|
|
58
53
|
@sock = @pull # for eval instance_exec
|
|
59
54
|
start_event_monitors if config.verbose >= 2
|
|
60
|
-
|
|
61
|
-
Barrier do |barrier|
|
|
62
|
-
barrier.async(annotation: "wait push peer") { @push.peer_connected.wait }
|
|
63
|
-
barrier.async(annotation: "wait pull peer") { @pull.peer_connected.wait }
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
if config.timeout
|
|
68
|
-
Fiber.scheduler.with_timeout(config.timeout, &wait_body)
|
|
69
|
-
else
|
|
70
|
-
wait_body.call
|
|
71
|
-
end
|
|
55
|
+
wait_for_peers_with_timeout if config.timeout
|
|
72
56
|
setup_sequential_transient(task)
|
|
73
57
|
@sock.instance_exec(&@recv_begin_proc) if @recv_begin_proc
|
|
74
58
|
sequential_message_loop
|
|
@@ -79,16 +63,27 @@ module OMQ
|
|
|
79
63
|
end
|
|
80
64
|
|
|
81
65
|
|
|
66
|
+
# With --timeout set, fail fast if peers never show up. Without
|
|
67
|
+
# it, there's no point waiting: PULL#receive blocks naturally
|
|
68
|
+
# and PUSH buffers up to send_hwm when no peer is present.
|
|
69
|
+
def wait_for_peers_with_timeout
|
|
70
|
+
Fiber.scheduler.with_timeout(config.timeout) do
|
|
71
|
+
Barrier do |barrier|
|
|
72
|
+
barrier.async(annotation: "wait push peer") { @push.peer_connected.wait }
|
|
73
|
+
barrier.async(annotation: "wait pull peer") { @pull.peer_connected.wait }
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
|
|
82
79
|
def build_pull_push(in_eps, out_eps)
|
|
83
80
|
kwargs = config.ffi ? { backend: :ffi } : {}
|
|
84
81
|
pull = OMQ::PULL.new(**kwargs)
|
|
85
82
|
push = OMQ::PUSH.new(**kwargs)
|
|
86
83
|
SocketSetup.apply_options(pull, config)
|
|
87
84
|
SocketSetup.apply_options(push, config)
|
|
88
|
-
pull
|
|
89
|
-
push
|
|
90
|
-
SocketSetup.attach_endpoints(pull, in_eps, verbose: config.verbose >= 1)
|
|
91
|
-
SocketSetup.attach_endpoints(push, out_eps, verbose: config.verbose >= 1)
|
|
85
|
+
SocketSetup.attach_endpoints(pull, in_eps, verbose: config.verbose)
|
|
86
|
+
SocketSetup.attach_endpoints(push, out_eps, verbose: config.verbose)
|
|
92
87
|
[pull, push]
|
|
93
88
|
end
|
|
94
89
|
|
|
@@ -189,19 +184,10 @@ module OMQ
|
|
|
189
184
|
|
|
190
185
|
|
|
191
186
|
def start_event_monitors
|
|
192
|
-
|
|
187
|
+
trace = config.verbose >= 3
|
|
193
188
|
[@pull, @push].each do |sock|
|
|
194
|
-
sock.monitor(verbose:
|
|
195
|
-
|
|
196
|
-
when :message_sent
|
|
197
|
-
$stderr.write("omq: >> #{Formatter.preview(event.detail[:parts])}\n")
|
|
198
|
-
when :message_received
|
|
199
|
-
$stderr.write("omq: << #{Formatter.preview(event.detail[:parts])}\n")
|
|
200
|
-
else
|
|
201
|
-
ep = event.endpoint ? " #{event.endpoint}" : ""
|
|
202
|
-
detail = event.detail ? " #{event.detail}" : ""
|
|
203
|
-
$stderr.write("omq: #{event.type}#{ep}#{detail}\n")
|
|
204
|
-
end
|
|
189
|
+
sock.monitor(verbose: trace) do |event|
|
|
190
|
+
Term.write_event(event, config.verbose)
|
|
205
191
|
end
|
|
206
192
|
end
|
|
207
193
|
end
|
data/lib/omq/cli/pipe_worker.rb
CHANGED
|
@@ -20,7 +20,7 @@ module OMQ
|
|
|
20
20
|
setup_sockets
|
|
21
21
|
log_endpoints if @config.verbose >= 1
|
|
22
22
|
start_monitors if @config.verbose >= 2
|
|
23
|
-
|
|
23
|
+
wait_for_peers_with_timeout if @config.timeout
|
|
24
24
|
compile_expr
|
|
25
25
|
run_message_loop
|
|
26
26
|
run_end_block
|
|
@@ -42,16 +42,15 @@ module OMQ
|
|
|
42
42
|
@push = OMQ::PUSH.new(**kwargs)
|
|
43
43
|
OMQ::CLI::SocketSetup.apply_options(@pull, @config)
|
|
44
44
|
OMQ::CLI::SocketSetup.apply_options(@push, @config)
|
|
45
|
-
@pull
|
|
46
|
-
@push
|
|
47
|
-
OMQ::CLI::SocketSetup.attach_endpoints(@pull, @in_eps, verbose: false)
|
|
48
|
-
OMQ::CLI::SocketSetup.attach_endpoints(@push, @out_eps, verbose: false)
|
|
45
|
+
OMQ::CLI::SocketSetup.attach_endpoints(@pull, @in_eps, verbose: 0)
|
|
46
|
+
OMQ::CLI::SocketSetup.attach_endpoints(@push, @out_eps, verbose: 0)
|
|
49
47
|
end
|
|
50
48
|
|
|
51
49
|
|
|
52
50
|
def log_endpoints
|
|
53
|
-
@in_eps.each
|
|
54
|
-
|
|
51
|
+
(@in_eps + @out_eps).each do |ep|
|
|
52
|
+
@log_port.send(OMQ::CLI::Term.format_attach(ep.bind? ? :bind : :connect, ep.url, @config.verbose))
|
|
53
|
+
end
|
|
55
54
|
end
|
|
56
55
|
|
|
57
56
|
|
|
@@ -59,30 +58,21 @@ module OMQ
|
|
|
59
58
|
trace = @config.verbose >= 3
|
|
60
59
|
[@pull, @push].each do |sock|
|
|
61
60
|
sock.monitor(verbose: trace) do |event|
|
|
62
|
-
@log_port.send(format_event(event))
|
|
61
|
+
@log_port.send(OMQ::CLI::Term.format_event(event, @config.verbose))
|
|
63
62
|
end
|
|
64
63
|
end
|
|
65
64
|
end
|
|
66
65
|
|
|
67
66
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
"omq: #{event.type}#{ep}#{detail}"
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
def wait_for_peers
|
|
83
|
-
Barrier do |barrier|
|
|
84
|
-
barrier.async { @pull.peer_connected.wait }
|
|
85
|
-
barrier.async { @push.peer_connected.wait }
|
|
67
|
+
# With --timeout set, fail fast if peers never show up. Without
|
|
68
|
+
# it, there's no point waiting: PULL#receive blocks naturally
|
|
69
|
+
# and PUSH buffers up to send_hwm when no peer is present.
|
|
70
|
+
def wait_for_peers_with_timeout
|
|
71
|
+
Fiber.scheduler.with_timeout(@config.timeout) do
|
|
72
|
+
Barrier do |barrier|
|
|
73
|
+
barrier.async { @pull.peer_connected.wait }
|
|
74
|
+
barrier.async { @push.peer_connected.wait }
|
|
75
|
+
end
|
|
86
76
|
end
|
|
87
77
|
end
|
|
88
78
|
|
data/lib/omq/cli/socket_setup.rb
CHANGED
|
@@ -7,11 +7,12 @@ module OMQ
|
|
|
7
7
|
#
|
|
8
8
|
module SocketSetup
|
|
9
9
|
# Default high water mark applied when the user does not pass
|
|
10
|
-
# --hwm. Lower than libzmq's default (1000) to keep
|
|
11
|
-
#
|
|
12
|
-
# debugging, short-lived pipelines).
|
|
13
|
-
#
|
|
14
|
-
|
|
10
|
+
# --hwm. Lower than libzmq's default (1000) to keep memory
|
|
11
|
+
# footprint bounded for the typical CLI use cases (interactive
|
|
12
|
+
# debugging, short-lived pipelines). 64 matches the recv pump's
|
|
13
|
+
# per-fairness-batch limit (one batch exactly fills a full
|
|
14
|
+
# queue).
|
|
15
|
+
DEFAULT_HWM = 64
|
|
15
16
|
|
|
16
17
|
# Default max inbound message size applied when the user does not
|
|
17
18
|
# pass --recv-maxsz. The omq library itself is unlimited by default;
|
|
@@ -57,30 +58,32 @@ module OMQ
|
|
|
57
58
|
|
|
58
59
|
|
|
59
60
|
# Bind/connect +sock+ using URL strings from +config.binds+ / +config.connects+.
|
|
61
|
+
# +verbose+ is the integer verbosity level (0 = silent).
|
|
60
62
|
#
|
|
61
|
-
def self.attach(sock, config, verbose:
|
|
63
|
+
def self.attach(sock, config, verbose: 0)
|
|
62
64
|
config.binds.each do |url|
|
|
63
65
|
sock.bind(url)
|
|
64
|
-
|
|
66
|
+
CLI::Term.write_attach(:bind, sock.last_endpoint, verbose) if verbose >= 1
|
|
65
67
|
end
|
|
66
68
|
config.connects.each do |url|
|
|
67
69
|
sock.connect(url)
|
|
68
|
-
|
|
70
|
+
CLI::Term.write_attach(:connect, url, verbose) if verbose >= 1
|
|
69
71
|
end
|
|
70
72
|
end
|
|
71
73
|
|
|
72
74
|
|
|
73
75
|
# Bind/connect +sock+ from an Array of Endpoint objects.
|
|
74
76
|
# Used by PipeRunner, which works with structured endpoint lists.
|
|
77
|
+
# +verbose+ is the integer verbosity level (0 = silent).
|
|
75
78
|
#
|
|
76
|
-
def self.attach_endpoints(sock, endpoints, verbose:
|
|
79
|
+
def self.attach_endpoints(sock, endpoints, verbose: 0)
|
|
77
80
|
endpoints.each do |ep|
|
|
78
81
|
if ep.bind?
|
|
79
82
|
sock.bind(ep.url)
|
|
80
|
-
|
|
83
|
+
CLI::Term.write_attach(:bind, sock.last_endpoint, verbose) if verbose >= 1
|
|
81
84
|
else
|
|
82
85
|
sock.connect(ep.url)
|
|
83
|
-
|
|
86
|
+
CLI::Term.write_attach(:connect, ep.url, verbose) if verbose >= 1
|
|
84
87
|
end
|
|
85
88
|
end
|
|
86
89
|
end
|
data/lib/omq/cli/term.rb
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OMQ
|
|
4
|
+
module CLI
|
|
5
|
+
# Stateless terminal formatting and stderr writing helpers shared
|
|
6
|
+
# by every code path that emits verbose-driven log lines (event
|
|
7
|
+
# monitor callbacks in BaseRunner / PipeRunner, SocketSetup attach
|
|
8
|
+
# helpers, parallel/pipe Ractor workers).
|
|
9
|
+
#
|
|
10
|
+
# Pure module functions: no state, no instance, safe to call from
|
|
11
|
+
# any thread or Ractor. Errors and abort messages do *not* go
|
|
12
|
+
# through this module — they aren't logs.
|
|
13
|
+
#
|
|
14
|
+
module Term
|
|
15
|
+
module_function
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# Returns a stderr log line prefix. At verbose >= 4, prepends an
|
|
19
|
+
# ISO8601 UTC timestamp with µs precision so log traces become
|
|
20
|
+
# time-correlatable. Otherwise returns the empty string.
|
|
21
|
+
#
|
|
22
|
+
# @param verbose [Integer]
|
|
23
|
+
# @return [String]
|
|
24
|
+
def log_prefix(verbose)
|
|
25
|
+
return "" unless verbose && verbose >= 4
|
|
26
|
+
"#{Time.now.utc.strftime("%FT%T.%6N")}Z "
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# Formats one OMQ::MonitorEvent into a single log line (no
|
|
31
|
+
# trailing newline).
|
|
32
|
+
#
|
|
33
|
+
# @param event [OMQ::MonitorEvent]
|
|
34
|
+
# @param verbose [Integer]
|
|
35
|
+
# @return [String]
|
|
36
|
+
def format_event(event, verbose)
|
|
37
|
+
prefix = log_prefix(verbose)
|
|
38
|
+
case event.type
|
|
39
|
+
when :message_sent
|
|
40
|
+
"#{prefix}omq: >> #{Formatter.preview(event.detail[:parts])}"
|
|
41
|
+
when :message_received
|
|
42
|
+
"#{prefix}omq: << #{Formatter.preview(event.detail[:parts])}"
|
|
43
|
+
else
|
|
44
|
+
ep = event.endpoint ? " #{event.endpoint}" : ""
|
|
45
|
+
detail = event.detail ? " #{event.detail}" : ""
|
|
46
|
+
"#{prefix}omq: #{event.type}#{ep}#{detail}"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
# Formats an "attached endpoint" log line (Bound to / Connecting to).
|
|
52
|
+
#
|
|
53
|
+
# @param kind [:bind, :connect]
|
|
54
|
+
# @param url [String]
|
|
55
|
+
# @param verbose [Integer]
|
|
56
|
+
# @return [String]
|
|
57
|
+
def format_attach(kind, url, verbose)
|
|
58
|
+
verb = kind == :bind ? "Bound to" : "Connecting to"
|
|
59
|
+
"#{log_prefix(verbose)}#{verb} #{url}"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# Writes one formatted event line to +io+ (default $stderr).
|
|
64
|
+
#
|
|
65
|
+
# @param event [OMQ::MonitorEvent]
|
|
66
|
+
# @param verbose [Integer]
|
|
67
|
+
# @param io [#write] writable sink, default $stderr
|
|
68
|
+
# @return [void]
|
|
69
|
+
def write_event(event, verbose, io: $stderr)
|
|
70
|
+
io.write("#{format_event(event, verbose)}\n")
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
# Writes one "Bound to / Connecting to" line to +io+
|
|
75
|
+
# (default $stderr).
|
|
76
|
+
#
|
|
77
|
+
# @param kind [:bind, :connect]
|
|
78
|
+
# @param url [String]
|
|
79
|
+
# @param verbose [Integer]
|
|
80
|
+
# @param io [#write]
|
|
81
|
+
# @return [void]
|
|
82
|
+
def write_attach(kind, url, verbose, io: $stderr)
|
|
83
|
+
io.write("#{format_attach(kind, url, verbose)}\n")
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
data/lib/omq/cli/version.rb
CHANGED
data/lib/omq/cli.rb
CHANGED
|
@@ -5,6 +5,7 @@ require_relative "cli/version"
|
|
|
5
5
|
require_relative "cli/config"
|
|
6
6
|
require_relative "cli/cli_parser"
|
|
7
7
|
require_relative "cli/formatter"
|
|
8
|
+
require_relative "cli/term"
|
|
8
9
|
require_relative "cli/expression_evaluator"
|
|
9
10
|
require_relative "cli/socket_setup"
|
|
10
11
|
require_relative "cli/routing_helper"
|
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.
|
|
4
|
+
version: 0.11.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Patrik Wenger
|
|
@@ -15,14 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - "~>"
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: '0.
|
|
18
|
+
version: '0.17'
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - "~>"
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: '0.
|
|
25
|
+
version: '0.17'
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: omq-ffi
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -185,6 +185,7 @@ files:
|
|
|
185
185
|
- lib/omq/cli/routing_helper.rb
|
|
186
186
|
- lib/omq/cli/scatter_gather.rb
|
|
187
187
|
- lib/omq/cli/socket_setup.rb
|
|
188
|
+
- lib/omq/cli/term.rb
|
|
188
189
|
- lib/omq/cli/transient_monitor.rb
|
|
189
190
|
- lib/omq/cli/version.rb
|
|
190
191
|
homepage: https://github.com/paddor/omq-cli
|