omq 0.4.0 → 0.4.1

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: d49a1c7caa7a1548615285ae294341b31833fd02bb60a7fa7cbfc0ed5c707d79
4
- data.tar.gz: db36537c5dab13faa9cbdbe611c282cbf9dd96726e88145f80c3aaa7bf3df8a5
3
+ metadata.gz: dd6af0ae414feae27d1119fe4f1144b680e7e039229d512fe2915cd0289fc4dc
4
+ data.tar.gz: b68f9a321eb93350fc175bd603f8d4c29e23518b6b2dfd2a13072eade5904c8f
5
5
  SHA512:
6
- metadata.gz: 3e3a9e5a0b9ee3857a2946e7468ea2ca30c87544fa75965c79b1ea905c3a8d969aeb94b49282acd502d2ffbb6a0db5b2952f7a18a17e90363f1c5ed13cfbecd4
7
- data.tar.gz: 1cb5f13312278d55684f22c420f17287a922633eebdfd143336415aafdc725dd7a38e23b5f9387cc55bf28acc0b125840c5770ef9112556b97b7c3cca8578ee6
6
+ metadata.gz: 3e17e9b4d867a7d2972b8caa4eff31dfd3c77095c60e9e5d9fdb53bc2646458dbfff244228065c145f0eb818d32f68bc196a7d0099fa4a5f2f02142f4c9a94b2
7
+ data.tar.gz: d0a7cc664076ea333433e5e14b5d1701219e4bf15200302cf0ab4420e928d50b2fe8d08d35889d69de6f35f7715b40f423195d33055a67f15af18404ee850536
data/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.1 — 2026-03-27
4
+
5
+ ### Improved
6
+
7
+ - Explicit flush after `send_message`/`send_command` instead of
8
+ `minimum_write_size: 0` workaround — enables write buffering
9
+ (multi-frame messages coalesced into fewer syscalls).
10
+ **+68% inproc throughput** (145k → 244k msg/s),
11
+ **-40% inproc latency** (15 → 9 µs)
12
+
13
+ ### Fixed
14
+
15
+ - Require `async ~> 2.38` for `Promise#wait?` (was `~> 2`)
16
+
3
17
  ## 0.4.0 — 2026-03-27
4
18
 
5
19
  ### Added (omqcat)
data/README.md CHANGED
@@ -7,11 +7,11 @@
7
7
 
8
8
  Pure Ruby implementation of the [ZMTP 3.1](https://rfc.zeromq.org/spec/23/) wire protocol ([ZeroMQ](https://zeromq.org/)) using the [Async](https://github.com/socketry/async) gem. No native libraries required.
9
9
 
10
- > **145k msg/s** inproc | **40k msg/s** ipc | **32k msg/s** tcp
10
+ > **244k msg/s** inproc | **47k msg/s** ipc | **36k msg/s** tcp
11
11
  >
12
- > **15 µs** inproc latency | **62 µs** ipc | **88 µs** tcp
12
+ > **9 µs** inproc latency | **47 µs** ipc | **61 µs** tcp
13
13
  >
14
- > Ruby 4.0 + YJIT on a Linux VM on a 2019 MacBook Pro (Intel) — [223k msg/s with io_uring](bench/README.md#io_uring)
14
+ > Ruby 4.0 + YJIT on a Linux VM on a 2019 MacBook Pro (Intel) — [~340k msg/s with io_uring](bench/README.md#io_uring)
15
15
 
16
16
  ---
17
17
 
@@ -121,19 +121,19 @@ req = ØMQ::REQ.new(">tcp://localhost:5555")
121
121
 
122
122
  ## Performance
123
123
 
124
- Benchmarked with benchmark-ips on Linux x86_64 (Ruby 4.0.1 +YJIT):
124
+ Benchmarked with benchmark-ips on Linux x86_64 (Ruby 4.0.2 +YJIT):
125
125
 
126
126
  #### Throughput (push/pull, 64 B messages)
127
127
 
128
128
  | inproc | ipc | tcp |
129
129
  |--------|-----|-----|
130
- | 184k/s | 35k/s | 18k/s |
130
+ | 244k/s | 47k/s | 36k/s |
131
131
 
132
132
  #### Latency (req/rep roundtrip)
133
133
 
134
134
  | inproc | ipc | tcp |
135
135
  |--------|-----|-----|
136
- | 13 µs | 70 µs | 97 µs |
136
+ | 9 µs | 47 µs | 61 µs |
137
137
 
138
138
  See [`bench/`](bench/) for full results and scripts.
139
139
 
@@ -142,7 +142,10 @@ See [`bench/`](bench/) for full results and scripts.
142
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
143
 
144
144
  ```sh
145
- # Echo server in one line
145
+ # Echo server
146
+ omqcat rep -b tcp://:5555 --echo
147
+
148
+ # Upcase server in one line
146
149
  omqcat rep -b tcp://:5555 -e '$F.map(&:upcase)'
147
150
 
148
151
  # Client
@@ -170,8 +173,10 @@ omqcat pull -b tcp://:5557 -J
170
173
  omqcat push -c tcp://remote:5557 -z < data.txt
171
174
  omqcat pull -b tcp://:5557 -z
172
175
 
173
- # CURVE encryption (auto-detected from env vars)
174
- SERVER_KEY=... omqcat req -c tcp://secure:5555 -D "secret"
176
+ # CURVE encryption
177
+ omqcat rep -b tcp://:5555 -D "secret" --curve-server
178
+ # prints: OMQ_SERVER_KEY='...'
179
+ omqcat req -c tcp://localhost:5555 --curve-server-key '...'
175
180
  ```
176
181
 
177
182
  The `-e` flag runs Ruby inside the socket instance — the full socket API (`self <<`, `send`, `subscribe`, ...) is available. Use `-r` to require gems:
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.4.0"
4
+ VERSION = "0.4.1"
5
5
  end
@@ -92,6 +92,7 @@ module OMQ
92
92
  @io.write(Codec::Frame.new(part, more: more).to_wire)
93
93
  end
94
94
  end
95
+ @io.flush
95
96
  end
96
97
  end
97
98
 
@@ -156,6 +157,7 @@ module OMQ
156
157
  else
157
158
  @io.write(command.to_frame.to_wire)
158
159
  end
160
+ @io.flush
159
161
  end
160
162
  end
161
163
 
@@ -32,7 +32,7 @@ module OMQ
32
32
  loop do
33
33
  client = server.accept
34
34
  Reactor.run do
35
- engine.handle_accepted(IO::Stream::Buffered.wrap(client, minimum_write_size: 0), endpoint: endpoint)
35
+ engine.handle_accepted(IO::Stream::Buffered.wrap(client), endpoint: endpoint)
36
36
  rescue ProtocolError, *ZMTP::CONNECTION_LOST
37
37
  # peer disconnected during handshake
38
38
  rescue
@@ -57,7 +57,7 @@ module OMQ
57
57
  path = parse_path(endpoint)
58
58
  sock_path = to_socket_path(path)
59
59
  sock = UNIXSocket.new(sock_path)
60
- engine.handle_connected(IO::Stream::Buffered.wrap(sock, minimum_write_size: 0), endpoint: endpoint)
60
+ engine.handle_connected(IO::Stream::Buffered.wrap(sock), endpoint: endpoint)
61
61
  end
62
62
 
63
63
  private
@@ -29,7 +29,7 @@ module OMQ
29
29
  loop do
30
30
  client = server.accept
31
31
  Reactor.run do
32
- engine.handle_accepted(IO::Stream::Buffered.wrap(client, minimum_write_size: 0), endpoint: resolved)
32
+ engine.handle_accepted(IO::Stream::Buffered.wrap(client), endpoint: resolved)
33
33
  rescue ProtocolError, *ZMTP::CONNECTION_LOST
34
34
  # peer disconnected during handshake
35
35
  rescue
@@ -53,7 +53,7 @@ module OMQ
53
53
  def connect(endpoint, engine)
54
54
  host, port = parse_endpoint(endpoint)
55
55
  sock = TCPSocket.new(host, port)
56
- engine.handle_connected(IO::Stream::Buffered.wrap(sock, minimum_write_size: 0), endpoint: endpoint)
56
+ engine.handle_connected(IO::Stream::Buffered.wrap(sock), endpoint: endpoint)
57
57
  end
58
58
 
59
59
  private
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.4.0
4
+ version: 0.4.1
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: '2'
18
+ version: '2.38'
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: '2'
25
+ version: '2.38'
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: io-stream
28
28
  requirement: !ruby/object:Gem::Requirement