omq 0.3.0 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2cda9b6329a0fdeef3ad3f7bf23522de62917ed6652209c2f39169cb62366b9e
4
- data.tar.gz: 2e86fe3f178c7959e2cc79488770c20a72522bb279909f2f85189ae56d0fe4c9
3
+ metadata.gz: 27a1d700594261a36d3212b00ff84e15be3053a32db07a04a48aa0eb52fec902
4
+ data.tar.gz: 2797e4863af5cfcde9fe446c79929705e6ab17656ba016532b54d6c6b57564b9
5
5
  SHA512:
6
- metadata.gz: 7b3287cc83b47ec7721011aa08cfb5dbc11c1e58affd9c75b708cfd6112f7d78870aa3831f017811bdd06c98e8969283e598b4ad2f62ecb6356675a61b2b124e
7
- data.tar.gz: 2d2c118209e4a4d8306359aa76eb33e3d1512a02736c2a57b484139afa3c5de726abc770280321fa5f42e02b1900d4bdc0c48cd4f5792eb48c9221cd77694d17
6
+ metadata.gz: a116b039dc996a0099bbb86e8c138fd71f03051bd23c142b653e1c8e932e541245476bed51a47183ecb3723f9f86b30f36b6e3956b77494f8d77c924354f39ad
7
+ data.tar.gz: bdd7a62bb68390c942ebb1517981ca69d0efab007f3be7d3149fcccb525ad9b2cb279689ba2ec640db0f6057d6d7219e804074bb5ba4eb4d8339517bf6de5805
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.2 — 2026-03-26
4
+
5
+ ### Improved
6
+
7
+ - Hide the warning about the experimental `IO::Buffer` (used by io-stream)
8
+
9
+ ## 0.3.1 — 2026-03-26
10
+
11
+ ### Improved
12
+
13
+ - `omqcat --help` responds in ~90ms (was ~470ms) — defer heavy gem loading
14
+ until after option parsing
15
+
3
16
  ## 0.3.0 — 2026-03-26
4
17
 
5
18
  ### Added
data/README.md CHANGED
@@ -137,6 +137,52 @@ Benchmarked with benchmark-ips on Linux x86_64 (Ruby 4.0.1 +YJIT):
137
137
 
138
138
  See [`bench/`](bench/) for full results and scripts.
139
139
 
140
+ ## omqcat — CLI tool
141
+
142
+ `omqcat` is a command-line tool for sending and receiving messages on any OMQ socket. Like `nngcat` from libnng, but with Ruby superpowers.
143
+
144
+ ```sh
145
+ # Echo server in one line
146
+ omqcat rep -b tcp://:5555 -e '$F.map(&:upcase)'
147
+
148
+ # Client
149
+ echo "hello" | omqcat req -c tcp://localhost:5555
150
+ # => HELLO
151
+
152
+ # PUB/SUB
153
+ omqcat sub -b tcp://:5556 -s "weather." &
154
+ echo "weather.nyc 72F" | omqcat pub -c tcp://localhost:5556 -d 0.3
155
+
156
+ # Pipeline with filtering
157
+ tail -f /var/log/syslog | omqcat push -c tcp://collector:5557
158
+ omqcat pull -b tcp://:5557 -e '$F.first.include?("error") ? $F : nil'
159
+
160
+ # Multipart messages via tabs
161
+ printf "routing-key\tpayload data" | omqcat push -c tcp://localhost:5557
162
+ omqcat pull -b tcp://:5557
163
+ # => routing-key payload data
164
+
165
+ # JSONL for structured data
166
+ echo '["key","value"]' | omqcat push -c tcp://localhost:5557 -J
167
+ omqcat pull -b tcp://:5557 -J
168
+
169
+ # Zstandard compression
170
+ omqcat push -c tcp://remote:5557 -z < data.txt
171
+ omqcat pull -b tcp://:5557 -z
172
+
173
+ # CURVE encryption (auto-detected from env vars)
174
+ SERVER_KEY=... omqcat req -c tcp://secure:5555 -D "secret"
175
+ ```
176
+
177
+ The `-e` flag runs Ruby inside the socket instance — the full socket API (`self <<`, `send`, `subscribe`, ...) is available. Use `-r` to require gems:
178
+
179
+ ```sh
180
+ omqcat sub -c tcp://localhost:5556 -s "" -r json \
181
+ -e 'JSON.parse($F.first)["temperature"]'
182
+ ```
183
+
184
+ Formats: `--ascii` (default, tab-separated), `--quoted`, `--raw`, `--jsonl`, `--msgpack`. See `omqcat --help` for all options.
185
+
140
186
  ## Interop with native ZMQ
141
187
 
142
188
  OMQ speaks ZMTP 3.1 on the wire and interoperates with libzmq, CZMQ, pyzmq, etc. over **tcp** and **ipc**. The `inproc://` transport is OMQ-internal (in-process Ruby queues) and is not visible to native ZMQ running in the same process — use `ipc://` to talk across library boundaries.
data/exe/omqcat CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
+ Warning[:experimental] = false
3
4
 
4
5
  #
5
6
  # omqcat — command-line access to OMQ (ZeroMQ) sockets.
@@ -12,29 +13,9 @@
12
13
  # omqcat sub -c tcp://localhost:5556 -s "weather."
13
14
  #
14
15
 
15
- require "omq"
16
- require "async"
17
16
  require "optparse"
18
- require "json"
19
- require "console"
20
17
 
21
- HAS_MSGPACK = begin; require "msgpack"; true; rescue LoadError; false; end
22
- HAS_ZSTD = begin; require "zstd-ruby"; true; rescue LoadError; false; end
23
-
24
- SOCKET_TYPES = {
25
- "req" => OMQ::REQ,
26
- "rep" => OMQ::REP,
27
- "pub" => OMQ::PUB,
28
- "sub" => OMQ::SUB,
29
- "push" => OMQ::PUSH,
30
- "pull" => OMQ::PULL,
31
- "pair" => OMQ::PAIR,
32
- "dealer" => OMQ::DEALER,
33
- "router" => OMQ::ROUTER,
34
- }.freeze
35
-
36
- SEND_ONLY = [OMQ::PUB, OMQ::PUSH].freeze
37
- RECV_ONLY = [OMQ::SUB, OMQ::PULL].freeze
18
+ SOCKET_TYPE_NAMES = %w[req rep pub sub push pull pair dealer router].freeze
38
19
 
39
20
 
40
21
  # ── Option parsing ──────────────────────────────────────────────────
@@ -61,7 +42,7 @@ opts = {
61
42
 
62
43
  parser = OptionParser.new do |o|
63
44
  o.banner = "Usage: omqcat TYPE [options]\n\n" \
64
- "Types: #{SOCKET_TYPES.keys.join(', ')}\n\n"
45
+ "Types: #{SOCKET_TYPE_NAMES.join(', ')}\n\n"
65
46
 
66
47
  o.separator "Connection:"
67
48
  o.on("-c", "--connect URL", "Connect to endpoint (repeatable)") { |v| opts[:connects] << v }
@@ -102,7 +83,7 @@ parser = OptionParser.new do |o|
102
83
  o.separator "\nOther:"
103
84
  o.on("-v", "--verbose", "Print connection events to stderr") { opts[:verbose] = true }
104
85
  o.on("-q", "--quiet", "Suppress message output") { opts[:quiet] = true }
105
- o.on("-V", "--version") { puts "omqcat #{OMQ::VERSION}"; exit }
86
+ o.on("-V", "--version") { require "omq"; puts "omqcat #{OMQ::VERSION}"; exit }
106
87
  o.on("-h", "--help") { puts o; exit }
107
88
  end
108
89
 
@@ -114,16 +95,39 @@ end
114
95
 
115
96
  type_name = ARGV.shift
116
97
  abort parser.to_s unless type_name
117
- klass = SOCKET_TYPES[type_name.downcase]
118
- abort "Unknown socket type: #{type_name}. Known: #{SOCKET_TYPES.keys.join(', ')}" unless klass
98
+ abort "Unknown socket type: #{type_name}. Known: #{SOCKET_TYPE_NAMES.join(', ')}" unless SOCKET_TYPE_NAMES.include?(type_name.downcase)
119
99
 
120
- # ── Validation ──────────────────────────────────────────────────────
100
+ # ── Validation (fast, before loading gems) ──────────────────────────
121
101
 
122
102
  abort "At least one --connect or --bind is required" if opts[:connects].empty? && opts[:binds].empty?
123
103
  abort "--data and --file are mutually exclusive" if opts[:data] && opts[:file]
124
- abort "--subscribe is only valid for SUB" if !opts[:subscribes].empty? && klass != OMQ::SUB
125
- abort "--identity is only valid for DEALER/ROUTER" if opts[:identity] && ![OMQ::DEALER, OMQ::ROUTER].include?(klass)
126
- abort "--target is only valid for ROUTER" if opts[:target] && klass != OMQ::ROUTER
104
+ abort "--subscribe is only valid for SUB" if !opts[:subscribes].empty? && type_name.downcase != "sub"
105
+ abort "--identity is only valid for DEALER/ROUTER" if opts[:identity] && !%w[dealer router].include?(type_name.downcase)
106
+ abort "--target is only valid for ROUTER" if opts[:target] && type_name.downcase != "router"
107
+
108
+ # ── Load gems ───────────────────────────────────────────────────────
109
+
110
+ require "omq"
111
+ require "async"
112
+ require "json"
113
+ require "console"
114
+
115
+ HAS_MSGPACK = begin; require "msgpack"; true; rescue LoadError; false; end
116
+ HAS_ZSTD = begin; require "zstd-ruby"; true; rescue LoadError; false; end
117
+
118
+ SOCKET_TYPES = {
119
+ "req" => OMQ::REQ, "rep" => OMQ::REP,
120
+ "pub" => OMQ::PUB, "sub" => OMQ::SUB,
121
+ "push" => OMQ::PUSH, "pull" => OMQ::PULL,
122
+ "pair" => OMQ::PAIR,
123
+ "dealer" => OMQ::DEALER, "router" => OMQ::ROUTER,
124
+ }.freeze
125
+
126
+ SEND_ONLY = [OMQ::PUB, OMQ::PUSH].freeze
127
+ RECV_ONLY = [OMQ::SUB, OMQ::PULL].freeze
128
+
129
+ klass = SOCKET_TYPES[type_name.downcase]
130
+
127
131
  abort "--msgpack requires the msgpack gem" if opts[:format] == :msgpack && !HAS_MSGPACK
128
132
  abort "--compress requires the zstd-ruby gem" if opts[:compress] && !HAS_ZSTD
129
133
 
data/lib/omq/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OMQ
4
- VERSION = "0.3.0"
4
+ VERSION = "0.3.2"
5
5
  end
@@ -35,7 +35,7 @@ module OMQ
35
35
  engine.handle_accepted(IO::Stream::Buffered.wrap(client, minimum_write_size: 0), endpoint: endpoint)
36
36
  rescue ProtocolError, *ZMTP::CONNECTION_LOST
37
37
  # peer disconnected during handshake
38
- rescue => e
38
+ rescue
39
39
  client&.close rescue nil
40
40
  raise
41
41
  end
@@ -32,7 +32,7 @@ module OMQ
32
32
  engine.handle_accepted(IO::Stream::Buffered.wrap(client, minimum_write_size: 0), endpoint: resolved)
33
33
  rescue ProtocolError, *ZMTP::CONNECTION_LOST
34
34
  # peer disconnected during handshake
35
- rescue => e
35
+ rescue
36
36
  client&.close rescue nil
37
37
  raise
38
38
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omq
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Patrik Wenger