omq-cli 0.7.0 → 0.7.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 +20 -0
- data/lib/omq/cli/base_runner.rb +7 -13
- data/lib/omq/cli/pipe.rb +28 -130
- data/lib/omq/cli/pipe_worker.rb +204 -0
- data/lib/omq/cli/version.rb +1 -1
- data/lib/omq/cli.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5af8706d0afd5ad199301ec7b37a47a232c5732a930eada3696a9f60a31aecc4
|
|
4
|
+
data.tar.gz: 6e5b15d9bb2af20181cccbc71d5b4d432938660a8e052d62598c18386ddf2a5d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8d35e218e4327b8a0c22c6ce15d9d205f62feffeec2fa2afd21cda6fcef96724645ea76922f0d0dd67099883b2795a0443211bbabf729c4c857e77e1a3b4299b
|
|
7
|
+
data.tar.gz: 34af31e1dc6605c6b90bc7dcb3f519755d13a12e71f4417de7a5d07f71617610fc6d728f57f1be5f51bda6923d49fc1a6fc8cb1cbc6234d31c37ad392b8c3452
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.7.2 — 2026-04-07
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- **Cleaned up pipe.rb** — removed unused `@fmt` formatters, dead `log` method,
|
|
8
|
+
and `with_timeout` wrapper. Moved `preresolve_tcp` and `start_log_consumer` to
|
|
9
|
+
`PipeWorker` class methods.
|
|
10
|
+
- **Guard `with_timeout(nil)`** — `Fiber.scheduler.with_timeout(nil)` fires
|
|
11
|
+
immediately in Async; peer-wait and pipe sequential mode now skip the timeout
|
|
12
|
+
wrapper when `config.timeout` is nil.
|
|
13
|
+
|
|
14
|
+
## 0.7.1 — 2026-04-07
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- **Pipe `-P` preresolves TCP hostnames** — DNS resolution happens on the
|
|
19
|
+
main thread before spawning Ractors, avoiding `Ractor::IsolationError`
|
|
20
|
+
on `Resolv::DefaultResolver`. All resolved addresses (IPv4 + IPv6) are
|
|
21
|
+
passed to workers.
|
|
22
|
+
|
|
3
23
|
## 0.7.0 — 2026-04-07
|
|
4
24
|
|
|
5
25
|
### Changed
|
data/lib/omq/cli/base_runner.rb
CHANGED
|
@@ -107,12 +107,18 @@ module OMQ
|
|
|
107
107
|
|
|
108
108
|
|
|
109
109
|
def wait_for_peer
|
|
110
|
-
|
|
110
|
+
wait_body = proc do
|
|
111
111
|
@sock.peer_connected.wait
|
|
112
112
|
log "Peer connected"
|
|
113
113
|
wait_for_subscriber
|
|
114
114
|
apply_grace_period
|
|
115
115
|
end
|
|
116
|
+
|
|
117
|
+
if config.timeout
|
|
118
|
+
Fiber.scheduler.with_timeout(config.timeout, &wait_body)
|
|
119
|
+
else
|
|
120
|
+
wait_body.call
|
|
121
|
+
end
|
|
116
122
|
end
|
|
117
123
|
|
|
118
124
|
|
|
@@ -133,18 +139,6 @@ module OMQ
|
|
|
133
139
|
end
|
|
134
140
|
|
|
135
141
|
|
|
136
|
-
# ── Timeout helper ──────────────────────────────────────────────
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
def with_timeout(seconds)
|
|
140
|
-
if seconds
|
|
141
|
-
Async::Task.current.with_timeout(seconds) { yield }
|
|
142
|
-
else
|
|
143
|
-
yield
|
|
144
|
-
end
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
|
|
148
142
|
# ── Socket setup ────────────────────────────────────────────────
|
|
149
143
|
|
|
150
144
|
|
data/lib/omq/cli/pipe.rb
CHANGED
|
@@ -11,8 +11,7 @@ module OMQ
|
|
|
11
11
|
|
|
12
12
|
# @param config [Config] frozen CLI configuration
|
|
13
13
|
def initialize(config)
|
|
14
|
-
@config
|
|
15
|
-
@fmt = Formatter.new(config.format, compress: config.compress)
|
|
14
|
+
@config = config
|
|
16
15
|
@fmt_in = Formatter.new(config.format, compress: config.compress_in || config.compress)
|
|
17
16
|
@fmt_out = Formatter.new(config.format, compress: config.compress_out || config.compress)
|
|
18
17
|
end
|
|
@@ -43,30 +42,27 @@ module OMQ
|
|
|
43
42
|
end
|
|
44
43
|
|
|
45
44
|
|
|
46
|
-
def attach_endpoints(sock, endpoints)
|
|
47
|
-
SocketSetup.attach_endpoints(sock, endpoints, verbose: config.verbose >= 1)
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
|
|
51
45
|
# ── Sequential ───────────────────────────────────────────────────
|
|
52
46
|
|
|
53
47
|
|
|
54
48
|
def run_sequential(task)
|
|
55
49
|
in_eps, out_eps = resolve_endpoints
|
|
56
|
-
@pull, @push = build_pull_push(
|
|
57
|
-
{ linger: config.linger, recv_timeout: config.timeout },
|
|
58
|
-
{ linger: config.linger, send_timeout: config.timeout },
|
|
59
|
-
in_eps, out_eps
|
|
60
|
-
)
|
|
50
|
+
@pull, @push = build_pull_push(in_eps, out_eps)
|
|
61
51
|
compile_expr
|
|
62
52
|
@sock = @pull # for eval instance_exec
|
|
63
53
|
start_event_monitors if config.verbose >= 2
|
|
64
|
-
|
|
54
|
+
wait_body = proc do
|
|
65
55
|
Barrier do |barrier|
|
|
66
56
|
barrier.async(annotation: "wait push peer") { @push.peer_connected.wait }
|
|
67
57
|
barrier.async(annotation: "wait pull peer") { @pull.peer_connected.wait }
|
|
68
58
|
end
|
|
69
59
|
end
|
|
60
|
+
|
|
61
|
+
if config.timeout
|
|
62
|
+
Fiber.scheduler.with_timeout(config.timeout, &wait_body)
|
|
63
|
+
else
|
|
64
|
+
wait_body.call
|
|
65
|
+
end
|
|
70
66
|
setup_sequential_transient(task)
|
|
71
67
|
@sock.instance_exec(&@recv_begin_proc) if @recv_begin_proc
|
|
72
68
|
sequential_message_loop
|
|
@@ -87,13 +83,13 @@ module OMQ
|
|
|
87
83
|
end
|
|
88
84
|
|
|
89
85
|
|
|
90
|
-
def build_pull_push(
|
|
91
|
-
pull = OMQ::PULL.new(
|
|
92
|
-
push = OMQ::PUSH.new(
|
|
86
|
+
def build_pull_push(in_eps, out_eps)
|
|
87
|
+
pull = OMQ::PULL.new(linger: config.linger, recv_timeout: config.timeout)
|
|
88
|
+
push = OMQ::PUSH.new(linger: config.linger, send_timeout: config.timeout)
|
|
93
89
|
apply_socket_options(pull)
|
|
94
90
|
apply_socket_options(push)
|
|
95
|
-
attach_endpoints(pull, in_eps)
|
|
96
|
-
attach_endpoints(push, out_eps)
|
|
91
|
+
SocketSetup.attach_endpoints(pull, in_eps, verbose: config.verbose >= 1)
|
|
92
|
+
SocketSetup.attach_endpoints(push, out_eps, verbose: config.verbose >= 1)
|
|
97
93
|
[pull, push]
|
|
98
94
|
end
|
|
99
95
|
|
|
@@ -117,8 +113,7 @@ module OMQ
|
|
|
117
113
|
parts = @fmt_in.decompress(parts)
|
|
118
114
|
parts = eval_recv_expr(parts)
|
|
119
115
|
if parts && !parts.empty?
|
|
120
|
-
|
|
121
|
-
@push.send(out)
|
|
116
|
+
@push.send(@fmt_out.compress(parts))
|
|
122
117
|
end
|
|
123
118
|
i += 1
|
|
124
119
|
break if n && n > 0 && i >= n
|
|
@@ -132,121 +127,26 @@ module OMQ
|
|
|
132
127
|
def run_parallel(task)
|
|
133
128
|
OMQ.freeze_for_ractors!
|
|
134
129
|
in_eps, out_eps = resolve_endpoints
|
|
135
|
-
|
|
130
|
+
in_eps = PipeWorker.preresolve_tcp(in_eps)
|
|
131
|
+
out_eps = PipeWorker.preresolve_tcp(out_eps)
|
|
132
|
+
log_port, log_thread = PipeWorker.start_log_consumer
|
|
133
|
+
workers = config.parallel.times.map do
|
|
134
|
+
::Ractor.new(config, in_eps, out_eps, log_port) do |cfg, ins, outs, lport|
|
|
135
|
+
PipeWorker.new(cfg, ins, outs, lport).call
|
|
136
|
+
end
|
|
137
|
+
end
|
|
136
138
|
workers.each do |w|
|
|
137
139
|
w.join
|
|
138
140
|
rescue ::Ractor::RemoteError => e
|
|
139
141
|
$stderr.write("omq: Ractor error: #{e.cause&.message || e.message}\n")
|
|
140
142
|
end
|
|
143
|
+
ensure
|
|
144
|
+
log_port.close
|
|
145
|
+
log_thread.join
|
|
141
146
|
end
|
|
142
147
|
|
|
143
148
|
|
|
144
|
-
|
|
145
|
-
config.parallel.times.map do
|
|
146
|
-
::Ractor.new(config, in_eps, out_eps) do |cfg, ins, outs|
|
|
147
|
-
Async do
|
|
148
|
-
pull = OMQ::PULL.new(linger: cfg.linger)
|
|
149
|
-
push = OMQ::PUSH.new(linger: cfg.linger)
|
|
150
|
-
pull.recv_timeout = cfg.timeout if cfg.timeout
|
|
151
|
-
push.send_timeout = cfg.timeout if cfg.timeout
|
|
152
|
-
pull.reconnect_interval = cfg.reconnect_ivl if cfg.reconnect_ivl
|
|
153
|
-
push.reconnect_interval = cfg.reconnect_ivl if cfg.reconnect_ivl
|
|
154
|
-
pull.heartbeat_interval = cfg.heartbeat_ivl if cfg.heartbeat_ivl
|
|
155
|
-
push.heartbeat_interval = cfg.heartbeat_ivl if cfg.heartbeat_ivl
|
|
156
|
-
pull.send_hwm = cfg.send_hwm if cfg.send_hwm
|
|
157
|
-
pull.recv_hwm = cfg.recv_hwm if cfg.recv_hwm
|
|
158
|
-
push.send_hwm = cfg.send_hwm if cfg.send_hwm
|
|
159
|
-
push.recv_hwm = cfg.recv_hwm if cfg.recv_hwm
|
|
160
|
-
pull.sndbuf = cfg.sndbuf if cfg.sndbuf
|
|
161
|
-
pull.rcvbuf = cfg.rcvbuf if cfg.rcvbuf
|
|
162
|
-
push.sndbuf = cfg.sndbuf if cfg.sndbuf
|
|
163
|
-
push.rcvbuf = cfg.rcvbuf if cfg.rcvbuf
|
|
164
|
-
|
|
165
|
-
OMQ::CLI::SocketSetup.attach_endpoints(pull, ins, verbose: cfg.verbose >= 1)
|
|
166
|
-
OMQ::CLI::SocketSetup.attach_endpoints(push, outs, verbose: cfg.verbose >= 1)
|
|
167
|
-
|
|
168
|
-
Barrier do |barrier|
|
|
169
|
-
barrier.async { pull.peer_connected.wait }
|
|
170
|
-
barrier.async { push.peer_connected.wait }
|
|
171
|
-
end
|
|
172
|
-
|
|
173
|
-
begin_proc, end_proc, eval_proc =
|
|
174
|
-
OMQ::CLI::ExpressionEvaluator.compile_inside_ractor(cfg.recv_expr)
|
|
175
|
-
|
|
176
|
-
fmt_in = OMQ::CLI::Formatter.new(cfg.format, compress: cfg.compress_in || cfg.compress)
|
|
177
|
-
fmt_out = OMQ::CLI::Formatter.new(cfg.format, compress: cfg.compress_out || cfg.compress)
|
|
178
|
-
|
|
179
|
-
_ctx = Object.new
|
|
180
|
-
_ctx.instance_exec(&begin_proc) if begin_proc
|
|
181
|
-
|
|
182
|
-
n_count = cfg.count
|
|
183
|
-
begin
|
|
184
|
-
if eval_proc
|
|
185
|
-
if n_count && n_count > 0
|
|
186
|
-
n_count.times do
|
|
187
|
-
parts = pull.receive
|
|
188
|
-
break if parts.nil?
|
|
189
|
-
parts = OMQ::CLI::ExpressionEvaluator.normalize_result(
|
|
190
|
-
_ctx.instance_exec(fmt_in.decompress(parts), &eval_proc)
|
|
191
|
-
)
|
|
192
|
-
next if parts.nil?
|
|
193
|
-
push << fmt_out.compress(parts) unless parts.empty?
|
|
194
|
-
end
|
|
195
|
-
else
|
|
196
|
-
loop do
|
|
197
|
-
parts = pull.receive
|
|
198
|
-
break if parts.nil?
|
|
199
|
-
parts = OMQ::CLI::ExpressionEvaluator.normalize_result(
|
|
200
|
-
_ctx.instance_exec(fmt_in.decompress(parts), &eval_proc)
|
|
201
|
-
)
|
|
202
|
-
next if parts.nil?
|
|
203
|
-
push << fmt_out.compress(parts) unless parts.empty?
|
|
204
|
-
end
|
|
205
|
-
end
|
|
206
|
-
else
|
|
207
|
-
if n_count && n_count > 0
|
|
208
|
-
n_count.times do
|
|
209
|
-
parts = pull.receive
|
|
210
|
-
break if parts.nil?
|
|
211
|
-
push << fmt_out.compress(fmt_in.decompress(parts))
|
|
212
|
-
end
|
|
213
|
-
else
|
|
214
|
-
loop do
|
|
215
|
-
parts = pull.receive
|
|
216
|
-
break if parts.nil?
|
|
217
|
-
push << fmt_out.compress(fmt_in.decompress(parts))
|
|
218
|
-
end
|
|
219
|
-
end
|
|
220
|
-
end
|
|
221
|
-
rescue IO::TimeoutError, Async::TimeoutError
|
|
222
|
-
# recv timed out — fall through to END block
|
|
223
|
-
end
|
|
224
|
-
|
|
225
|
-
if end_proc
|
|
226
|
-
out = OMQ::CLI::ExpressionEvaluator.normalize_result(
|
|
227
|
-
_ctx.instance_exec(&end_proc)
|
|
228
|
-
)
|
|
229
|
-
push << fmt_out.compress(out) if out && !out.empty?
|
|
230
|
-
end
|
|
231
|
-
ensure
|
|
232
|
-
pull&.close
|
|
233
|
-
push&.close
|
|
234
|
-
end
|
|
235
|
-
end
|
|
236
|
-
end
|
|
237
|
-
end
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
# ── Shared helpers ────────────────────────────────────────────────
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
def with_timeout(seconds)
|
|
244
|
-
if seconds
|
|
245
|
-
Async::Task.current.with_timeout(seconds) { yield }
|
|
246
|
-
else
|
|
247
|
-
yield
|
|
248
|
-
end
|
|
249
|
-
end
|
|
149
|
+
# ── Expression eval ──────────────────────────────────────────────
|
|
250
150
|
|
|
251
151
|
|
|
252
152
|
def compile_expr
|
|
@@ -263,9 +163,7 @@ module OMQ
|
|
|
263
163
|
end
|
|
264
164
|
|
|
265
165
|
|
|
266
|
-
|
|
267
|
-
$stderr.write("#{msg}\n") if config.verbose >= 1
|
|
268
|
-
end
|
|
166
|
+
# ── Event monitoring ─────────────────────────────────────────────
|
|
269
167
|
|
|
270
168
|
|
|
271
169
|
def start_event_monitors
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OMQ
|
|
4
|
+
module CLI
|
|
5
|
+
# Worker that runs inside a Ractor for pipe -P parallel mode.
|
|
6
|
+
# Each worker owns its own Async reactor, PULL socket, and PUSH socket.
|
|
7
|
+
#
|
|
8
|
+
class PipeWorker
|
|
9
|
+
# Starts a Ractor::Port and a consumer thread that drains log
|
|
10
|
+
# messages to stderr sequentially. Returns [port, thread].
|
|
11
|
+
#
|
|
12
|
+
def self.start_log_consumer
|
|
13
|
+
port = Ractor::Port.new
|
|
14
|
+
thread = Thread.new(port) do |p|
|
|
15
|
+
loop do
|
|
16
|
+
$stderr.write("#{p.receive}\n")
|
|
17
|
+
rescue Ractor::ClosedError
|
|
18
|
+
break
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
[port, thread]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# Resolves TCP hostnames to IP addresses so Ractors don't touch
|
|
26
|
+
# Resolv::DefaultResolver (which is not shareable).
|
|
27
|
+
#
|
|
28
|
+
def self.preresolve_tcp(endpoints)
|
|
29
|
+
endpoints.flat_map do |ep|
|
|
30
|
+
url = ep.url
|
|
31
|
+
if url.start_with?("tcp://")
|
|
32
|
+
host, port = OMQ::Transport::TCP.parse_endpoint(url)
|
|
33
|
+
Addrinfo.getaddrinfo(host, port, nil, :STREAM).map do |addr|
|
|
34
|
+
ip = addr.ip_address
|
|
35
|
+
ip = "[#{ip}]" if ip.include?(":")
|
|
36
|
+
Endpoint.new("tcp://#{ip}:#{addr.ip_port}", ep.bind?)
|
|
37
|
+
end
|
|
38
|
+
else
|
|
39
|
+
ep
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def initialize(config, in_eps, out_eps, log_port)
|
|
46
|
+
@config = config
|
|
47
|
+
@in_eps = in_eps
|
|
48
|
+
@out_eps = out_eps
|
|
49
|
+
@log_port = log_port
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def call
|
|
54
|
+
Async do
|
|
55
|
+
setup_sockets
|
|
56
|
+
log_endpoints if @config.verbose >= 1
|
|
57
|
+
start_monitors if @config.verbose >= 2
|
|
58
|
+
wait_for_peers
|
|
59
|
+
compile_expr
|
|
60
|
+
run_message_loop
|
|
61
|
+
run_end_block
|
|
62
|
+
ensure
|
|
63
|
+
@pull&.close
|
|
64
|
+
@push&.close
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
private
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def setup_sockets
|
|
73
|
+
@pull = OMQ::PULL.new(linger: @config.linger)
|
|
74
|
+
@push = OMQ::PUSH.new(linger: @config.linger)
|
|
75
|
+
@pull.recv_timeout = @config.timeout if @config.timeout
|
|
76
|
+
@push.send_timeout = @config.timeout if @config.timeout
|
|
77
|
+
apply_socket_options(@pull)
|
|
78
|
+
apply_socket_options(@push)
|
|
79
|
+
OMQ::CLI::SocketSetup.attach_endpoints(@pull, @in_eps, verbose: false)
|
|
80
|
+
OMQ::CLI::SocketSetup.attach_endpoints(@push, @out_eps, verbose: false)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def apply_socket_options(sock)
|
|
85
|
+
sock.reconnect_interval = @config.reconnect_ivl if @config.reconnect_ivl
|
|
86
|
+
sock.heartbeat_interval = @config.heartbeat_ivl if @config.heartbeat_ivl
|
|
87
|
+
sock.send_hwm = @config.send_hwm if @config.send_hwm
|
|
88
|
+
sock.recv_hwm = @config.recv_hwm if @config.recv_hwm
|
|
89
|
+
sock.sndbuf = @config.sndbuf if @config.sndbuf
|
|
90
|
+
sock.rcvbuf = @config.rcvbuf if @config.rcvbuf
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def log_endpoints
|
|
95
|
+
@in_eps.each { |ep| @log_port.send(ep.bind? ? "Bound to #{ep.url}" : "Connecting to #{ep.url}") }
|
|
96
|
+
@out_eps.each { |ep| @log_port.send(ep.bind? ? "Bound to #{ep.url}" : "Connecting to #{ep.url}") }
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def start_monitors
|
|
101
|
+
trace = @config.verbose >= 3
|
|
102
|
+
[@pull, @push].each do |sock|
|
|
103
|
+
sock.monitor(verbose: trace) do |event|
|
|
104
|
+
@log_port.send(format_event(event))
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def format_event(event)
|
|
111
|
+
case event.type
|
|
112
|
+
when :message_sent
|
|
113
|
+
"omq: >> #{msg_preview(event.detail[:parts])}"
|
|
114
|
+
when :message_received
|
|
115
|
+
"omq: << #{msg_preview(event.detail[:parts])}"
|
|
116
|
+
else
|
|
117
|
+
ep = event.endpoint ? " #{event.endpoint}" : ""
|
|
118
|
+
detail = event.detail ? " #{event.detail}" : ""
|
|
119
|
+
"omq: #{event.type}#{ep}#{detail}"
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def msg_preview(parts)
|
|
125
|
+
parts.map { |p|
|
|
126
|
+
bytes = p.b
|
|
127
|
+
preview = bytes[0, 10].gsub(/[^[:print:]]/, ".")
|
|
128
|
+
bytes.bytesize > 10 ? "#{preview}... (#{bytes.bytesize}B)" : preview
|
|
129
|
+
}.join(" | ")
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def wait_for_peers
|
|
134
|
+
Barrier do |barrier|
|
|
135
|
+
barrier.async { @pull.peer_connected.wait }
|
|
136
|
+
barrier.async { @push.peer_connected.wait }
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def compile_expr
|
|
142
|
+
@begin_proc, @end_proc, @eval_proc =
|
|
143
|
+
OMQ::CLI::ExpressionEvaluator.compile_inside_ractor(@config.recv_expr)
|
|
144
|
+
@fmt_in = OMQ::CLI::Formatter.new(@config.format, compress: @config.compress_in || @config.compress)
|
|
145
|
+
@fmt_out = OMQ::CLI::Formatter.new(@config.format, compress: @config.compress_out || @config.compress)
|
|
146
|
+
@ctx = Object.new
|
|
147
|
+
@ctx.instance_exec(&@begin_proc) if @begin_proc
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def run_message_loop
|
|
152
|
+
n = @config.count
|
|
153
|
+
if @eval_proc
|
|
154
|
+
if n && n > 0
|
|
155
|
+
n.times do
|
|
156
|
+
parts = @pull.receive
|
|
157
|
+
break if parts.nil?
|
|
158
|
+
parts = OMQ::CLI::ExpressionEvaluator.normalize_result(
|
|
159
|
+
@ctx.instance_exec(@fmt_in.decompress(parts), &@eval_proc)
|
|
160
|
+
)
|
|
161
|
+
next if parts.nil?
|
|
162
|
+
@push << @fmt_out.compress(parts) unless parts.empty?
|
|
163
|
+
end
|
|
164
|
+
else
|
|
165
|
+
loop do
|
|
166
|
+
parts = @pull.receive
|
|
167
|
+
break if parts.nil?
|
|
168
|
+
parts = OMQ::CLI::ExpressionEvaluator.normalize_result(
|
|
169
|
+
@ctx.instance_exec(@fmt_in.decompress(parts), &@eval_proc)
|
|
170
|
+
)
|
|
171
|
+
next if parts.nil?
|
|
172
|
+
@push << @fmt_out.compress(parts) unless parts.empty?
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
else
|
|
176
|
+
if n && n > 0
|
|
177
|
+
n.times do
|
|
178
|
+
parts = @pull.receive
|
|
179
|
+
break if parts.nil?
|
|
180
|
+
@push << @fmt_out.compress(@fmt_in.decompress(parts))
|
|
181
|
+
end
|
|
182
|
+
else
|
|
183
|
+
loop do
|
|
184
|
+
parts = @pull.receive
|
|
185
|
+
break if parts.nil?
|
|
186
|
+
@push << @fmt_out.compress(@fmt_in.decompress(parts))
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
rescue IO::TimeoutError, Async::TimeoutError
|
|
191
|
+
# recv timed out — fall through to END block
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def run_end_block
|
|
196
|
+
return unless @end_proc
|
|
197
|
+
out = OMQ::CLI::ExpressionEvaluator.normalize_result(
|
|
198
|
+
@ctx.instance_exec(&@end_proc)
|
|
199
|
+
)
|
|
200
|
+
@push << @fmt_out.compress(out) if out && !out.empty?
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
data/lib/omq/cli/version.rb
CHANGED
data/lib/omq/cli.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.7.
|
|
4
|
+
version: 0.7.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Patrik Wenger
|
|
@@ -166,6 +166,7 @@ files:
|
|
|
166
166
|
- lib/omq/cli/formatter.rb
|
|
167
167
|
- lib/omq/cli/pair.rb
|
|
168
168
|
- lib/omq/cli/pipe.rb
|
|
169
|
+
- lib/omq/cli/pipe_worker.rb
|
|
169
170
|
- lib/omq/cli/pub_sub.rb
|
|
170
171
|
- lib/omq/cli/push_pull.rb
|
|
171
172
|
- lib/omq/cli/radio_dish.rb
|