omq 0.21.0 → 0.22.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 +38 -0
- data/lib/omq/routing/fan_out.rb +7 -8
- data/lib/omq/routing/sub.rb +27 -7
- data/lib/omq/routing/xsub.rb +12 -2
- data/lib/omq/transport/inproc/direct_pipe.rb +23 -8
- data/lib/omq/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: aa0683eef1c05982186c434cfbb21112518ec220e843207fa772a3cc3cd69ee9
|
|
4
|
+
data.tar.gz: 95b92509cac850c9b45380675fec60ed3db22cc21674ffde09901742b024f43a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 51b018f6e6d0fe83181e14fefc9f7cda13661cc3e071e2b83f2ed517e98e550eb22f9c7b7092696261ce4bd458a7355ccfe51cb44235c38df9004f6c72d7c31b
|
|
7
|
+
data.tar.gz: 7e4581c1f0e18714a30af54833d6cabef1001936d5f4126bde2fa6144dfe3b153b825dff82576a7abca0d61dc9f87b01f0a962f950c56c2d0a5803705addf1ca
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.22.0 — 2026-04-15
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **PUB/SUB interop with ZMTP 3.0 peers** (libzmq, JeroMQ, pyzmq,
|
|
8
|
+
NetMQ). OMQ previously sent `SUBSCRIBE`/`CANCEL` as ZMTP 3.1
|
|
9
|
+
command frames unconditionally; 3.0 peers expect message-form
|
|
10
|
+
(`\x01`/`\x00` + prefix data frames) and silently dropped them.
|
|
11
|
+
`Routing::Sub` and `Routing::XSub` now dispatch on
|
|
12
|
+
`conn.peer_minor`: command-form to ZMTP 3.1+ peers,
|
|
13
|
+
message-form to ZMTP 3.0 peers. `FanOut`'s subscription listener
|
|
14
|
+
already accepts both forms via `Protocol::ZMTP::Codec::Subscription.parse`,
|
|
15
|
+
so PUB/XPUB now also accept legacy message-form subscriptions
|
|
16
|
+
from 3.0 peers. Verified against JeroMQ in all six role/direction
|
|
17
|
+
combinations.
|
|
18
|
+
- **ZMTP/2.0 peers are now dropped loudly** during handshake
|
|
19
|
+
instead of hanging `read_exactly` forever. The underlying
|
|
20
|
+
`Greeting.read_from` helper in `protocol-zmtp` sniffs the
|
|
21
|
+
revision byte after 11 bytes and raises; the engine's existing
|
|
22
|
+
handshake-failure path closes the connection.
|
|
23
|
+
- **`Inproc::DirectPipe#read_frame`** now returns a data `Frame`
|
|
24
|
+
for non-command queue entries instead of silently dropping
|
|
25
|
+
them. Previously the fast-path `read_frame` only handled
|
|
26
|
+
`[:command, cmd]`-tagged items, so a message-form subscription
|
|
27
|
+
arriving on an inproc pipe was lost. Fallout from the PUB/SUB
|
|
28
|
+
fix above — without it the inproc tests for that path hung.
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
- **ZMTP 3.0 / 3.1 compat tests** (`test/omq/zmtp_30_compat_test.rb`).
|
|
33
|
+
Hand-crafted raw TCP peer fakes cover: OMQ SUB → 3.0 PUB (message-form),
|
|
34
|
+
OMQ SUB → 3.1 PUB (command-form), OMQ XSUB → 3.0 PUB, OMQ XSUB → 3.1 PUB,
|
|
35
|
+
and OMQ PUB accepting message-form SUBSCRIBE from a 3.0 SUB peer.
|
|
36
|
+
- **`Inproc::DirectPipe#peer_major` / `#peer_minor`** — hard-coded to
|
|
37
|
+
3/1 since both ends of an inproc pipe are OMQ. Lets the routing
|
|
38
|
+
layer dispatch uniformly on `conn.peer_minor` without special-casing
|
|
39
|
+
the transport.
|
|
40
|
+
|
|
3
41
|
## 0.21.0 — 2026-04-15
|
|
4
42
|
|
|
5
43
|
### Changed
|
data/lib/omq/routing/fan_out.rb
CHANGED
|
@@ -133,15 +133,14 @@ module OMQ
|
|
|
133
133
|
@tasks << @engine.spawn_conn_pump_task(conn, annotation: "subscription listener") do
|
|
134
134
|
loop do
|
|
135
135
|
frame = conn.read_frame
|
|
136
|
-
next unless frame.command?
|
|
137
136
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
137
|
+
case Protocol::ZMTP::Codec::Subscription.parse(frame)
|
|
138
|
+
in [:subscribe, prefix]
|
|
139
|
+
on_subscribe(conn, prefix)
|
|
140
|
+
in [:cancel, prefix]
|
|
141
|
+
on_cancel(conn, prefix)
|
|
142
|
+
else
|
|
143
|
+
next
|
|
145
144
|
end
|
|
146
145
|
end
|
|
147
146
|
end
|
data/lib/omq/routing/sub.rb
CHANGED
|
@@ -48,7 +48,7 @@ module OMQ
|
|
|
48
48
|
@connections << connection
|
|
49
49
|
|
|
50
50
|
@subscriptions.each do |prefix|
|
|
51
|
-
connection
|
|
51
|
+
send_subscribe(connection, prefix)
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
task = @engine.start_recv_pump(connection, @recv_queue)
|
|
@@ -76,9 +76,7 @@ module OMQ
|
|
|
76
76
|
#
|
|
77
77
|
def subscribe(prefix)
|
|
78
78
|
@subscriptions << prefix
|
|
79
|
-
@connections.each
|
|
80
|
-
conn.send_command(Protocol::ZMTP::Codec::Command.subscribe(prefix))
|
|
81
|
-
end
|
|
79
|
+
@connections.each { |conn| send_subscribe(conn, prefix) }
|
|
82
80
|
end
|
|
83
81
|
|
|
84
82
|
|
|
@@ -88,9 +86,7 @@ module OMQ
|
|
|
88
86
|
#
|
|
89
87
|
def unsubscribe(prefix)
|
|
90
88
|
@subscriptions.delete(prefix)
|
|
91
|
-
@connections.each
|
|
92
|
-
conn.send_command(Protocol::ZMTP::Codec::Command.cancel(prefix))
|
|
93
|
-
end
|
|
89
|
+
@connections.each { |conn| send_cancel(conn, prefix) }
|
|
94
90
|
end
|
|
95
91
|
|
|
96
92
|
|
|
@@ -103,6 +99,30 @@ module OMQ
|
|
|
103
99
|
@tasks.clear
|
|
104
100
|
end
|
|
105
101
|
|
|
102
|
+
|
|
103
|
+
private
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
# Sends a SUBSCRIBE to +conn+ using the wire form the peer understands:
|
|
107
|
+
# command-form for ZMTP 3.1+, legacy message-form for ZMTP 3.0.
|
|
108
|
+
#
|
|
109
|
+
def send_subscribe(conn, prefix)
|
|
110
|
+
if conn.peer_minor >= 1
|
|
111
|
+
conn.send_command(Protocol::ZMTP::Codec::Command.subscribe(prefix))
|
|
112
|
+
else
|
|
113
|
+
conn.send_message([Protocol::ZMTP::Codec::Subscription.body(prefix)])
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def send_cancel(conn, prefix)
|
|
119
|
+
if conn.peer_minor >= 1
|
|
120
|
+
conn.send_command(Protocol::ZMTP::Codec::Command.cancel(prefix))
|
|
121
|
+
else
|
|
122
|
+
conn.send_message([Protocol::ZMTP::Codec::Subscription.body(prefix, cancel: true)])
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
106
126
|
end
|
|
107
127
|
end
|
|
108
128
|
end
|
data/lib/omq/routing/xsub.rb
CHANGED
|
@@ -112,9 +112,19 @@ module OMQ
|
|
|
112
112
|
|
|
113
113
|
case flag
|
|
114
114
|
when 0x01
|
|
115
|
-
conn.
|
|
115
|
+
if conn.peer_minor >= 1
|
|
116
|
+
conn.send_command(Protocol::ZMTP::Codec::Command.subscribe(prefix))
|
|
117
|
+
else
|
|
118
|
+
conn.send_message([frame])
|
|
119
|
+
end
|
|
116
120
|
when 0x00
|
|
117
|
-
conn.
|
|
121
|
+
if conn.peer_minor >= 1
|
|
122
|
+
conn.send_command(Protocol::ZMTP::Codec::Command.cancel(prefix))
|
|
123
|
+
else
|
|
124
|
+
conn.send_message([frame])
|
|
125
|
+
end
|
|
126
|
+
else
|
|
127
|
+
next
|
|
118
128
|
end
|
|
119
129
|
end
|
|
120
130
|
end
|
|
@@ -20,6 +20,20 @@ module OMQ
|
|
|
20
20
|
attr_reader :peer_socket_type
|
|
21
21
|
|
|
22
22
|
|
|
23
|
+
# @return [Integer] always 3 — inproc peers are OMQ
|
|
24
|
+
#
|
|
25
|
+
def peer_major
|
|
26
|
+
3
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# @return [Integer] always 1 — inproc peers are OMQ (ZMTP 3.1)
|
|
31
|
+
#
|
|
32
|
+
def peer_minor
|
|
33
|
+
1
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
|
|
23
37
|
# @return [String] peer's identity
|
|
24
38
|
#
|
|
25
39
|
attr_reader :peer_identity
|
|
@@ -158,19 +172,20 @@ module OMQ
|
|
|
158
172
|
end
|
|
159
173
|
|
|
160
174
|
|
|
161
|
-
# Reads one
|
|
162
|
-
#
|
|
175
|
+
# Reads one frame. Used by PUB/XPUB subscription listeners,
|
|
176
|
+
# which must see both the legacy message-form subscription
|
|
177
|
+
# (ZMTP 3.0) and the command-form (ZMTP 3.1).
|
|
163
178
|
#
|
|
164
179
|
# @return [Protocol::ZMTP::Codec::Frame]
|
|
165
180
|
#
|
|
166
181
|
def read_frame
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
raise EOFError, "connection closed" if item.nil?
|
|
182
|
+
item = @receive_queue.dequeue
|
|
183
|
+
raise EOFError, "connection closed" if item.nil?
|
|
170
184
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
185
|
+
if item.is_a?(Array) && item.first == :command
|
|
186
|
+
Protocol::ZMTP::Codec::Frame.new(item[1].to_body, command: true)
|
|
187
|
+
else
|
|
188
|
+
Protocol::ZMTP::Codec::Frame.new(item.first || "".b)
|
|
174
189
|
end
|
|
175
190
|
end
|
|
176
191
|
|
data/lib/omq/version.rb
CHANGED
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
|
+
version: 0.22.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.8'
|
|
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.8'
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: async
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|