omq 0.28.2 → 0.28.3
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 +14 -0
- data/README.md +14 -4
- data/lib/omq/engine.rb +61 -10
- data/lib/omq/socket.rb +1 -2
- data/lib/omq/transport/inproc.rb +17 -2
- data/lib/omq/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8e5b7537e4771c3cf95f34bc0d6e48f5bcd49234234c7a4a2d7053e7dae0ce62
|
|
4
|
+
data.tar.gz: 2999ee7d27ae3e9c0b8235106d46aab741d5c17d4aa98ffd798ea91c2baa7082
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 35164b7ce34f04f267124da8347979b481712d2127ba49ae2fbee180b55c48fa93aaa82955e66a8215204d90b9b5163dbb6b278565da504bb41cefb977888d43
|
|
7
|
+
data.tar.gz: c5529115fd854bb87e987feba2767491f3c85bc643e855aae0f1359df889966718613596a4807a6dd4a58c4134e641b89762ebc6d209e362523692ac072f7c35
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.28.3] - 2026-07-30
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Made `inproc://` a compatibility alias for `ruby://` when no backend or
|
|
10
|
+
plugin registers a real `inproc` transport.
|
|
11
|
+
- Lazy-load the Rust backend from `omq/backend/rust`, matching
|
|
12
|
+
`omq/backend/libzmq`.
|
|
13
|
+
|
|
14
|
+
### Removed
|
|
15
|
+
|
|
16
|
+
- Removed the old `omq/rust` backend load path.
|
|
17
|
+
- Removed the old `omq/ffi` backend load path and `backend: :ffi` alias.
|
|
18
|
+
|
|
5
19
|
## 0.28.2 - 2026-07-28
|
|
6
20
|
|
|
7
21
|
### Fixed
|
data/README.md
CHANGED
|
@@ -34,8 +34,9 @@ walkthrough of every major pattern with working code.
|
|
|
34
34
|
knife for ØMQ. `gem install omq-cli`
|
|
35
35
|
- **Every socket pattern**: req/rep, pub/sub, push/pull, dealer/router,
|
|
36
36
|
xpub/xsub, pair, and all draft types
|
|
37
|
-
- **Every transport**: tcp, ipc (Unix domain sockets), inproc
|
|
38
|
-
queues)
|
|
37
|
+
- **Every transport**: tcp, ipc (Unix domain sockets), ruby/inproc
|
|
38
|
+
(in-process queues). `inproc://` aliases `ruby://` unless a backend
|
|
39
|
+
provides native inproc
|
|
39
40
|
- **Async-native**: built on fibers, non-blocking from the ground up
|
|
40
41
|
- **Works outside Async too**: a shared IO thread handles sockets for callers
|
|
41
42
|
that aren't inside a reactor, so simple scripts just work
|
|
@@ -214,6 +215,16 @@ echo "hello" | omq req -c tcp://localhost:5555
|
|
|
214
215
|
|
|
215
216
|
See the [omq-cli README](https://github.com/paddor/omq-cli) for full documentation.
|
|
216
217
|
|
|
218
|
+
## Optional Rust backend
|
|
219
|
+
|
|
220
|
+
Install `omq-backend-rust` for a Rust/omq-tokio backend. Same socket API,
|
|
221
|
+
but connection handling runs in native code on a Tokio runtime.
|
|
222
|
+
|
|
223
|
+
```ruby
|
|
224
|
+
require "omq/backend/rust"
|
|
225
|
+
push = OMQ::PUSH.new(backend: :rust)
|
|
226
|
+
```
|
|
227
|
+
|
|
217
228
|
## Optional libzmq backend
|
|
218
229
|
|
|
219
230
|
Install `omq-backend-libzmq` for a Ruby 4.0+ libzmq backend. Same socket
|
|
@@ -227,8 +238,7 @@ push = OMQ::PUSH.new(backend: :libzmq)
|
|
|
227
238
|
```
|
|
228
239
|
|
|
229
240
|
Requires the `ffi` gem and a system libzmq 4.x. `ffi` is not a runtime
|
|
230
|
-
dependency of `omq`.
|
|
231
|
-
names still work.
|
|
241
|
+
dependency of `omq`.
|
|
232
242
|
|
|
233
243
|
## Companion Gems
|
|
234
244
|
|
data/lib/omq/engine.rb
CHANGED
|
@@ -192,8 +192,8 @@ module OMQ
|
|
|
192
192
|
def bind(endpoint, parent: nil, **opts)
|
|
193
193
|
OMQ.freeze_for_ractors!
|
|
194
194
|
capture_parent_task(parent: parent)
|
|
195
|
-
transport =
|
|
196
|
-
listener
|
|
195
|
+
endpoint, transport = resolve_endpoint(endpoint)
|
|
196
|
+
listener = transport.listener(endpoint, self, **opts)
|
|
197
197
|
|
|
198
198
|
start_accept_loops(listener)
|
|
199
199
|
|
|
@@ -214,15 +214,14 @@ module OMQ
|
|
|
214
214
|
def connect(endpoint, parent: nil, **opts)
|
|
215
215
|
OMQ.freeze_for_ractors!
|
|
216
216
|
capture_parent_task(parent: parent)
|
|
217
|
-
|
|
217
|
+
endpoint, transport = resolve_endpoint(endpoint)
|
|
218
|
+
validate_endpoint!(endpoint, transport)
|
|
218
219
|
|
|
219
220
|
if endpoint.start_with?("ruby://")
|
|
220
221
|
# Ruby in-process connect is synchronous and instant — no Dialer
|
|
221
|
-
transport = transport_for(endpoint)
|
|
222
222
|
transport.connect(endpoint, self, **opts)
|
|
223
223
|
@dialers[endpoint] = :ruby # sentinel for reconnect intent
|
|
224
224
|
else
|
|
225
|
-
transport = transport_for(endpoint)
|
|
226
225
|
@dialers[endpoint] = transport.dialer(endpoint, self, **opts)
|
|
227
226
|
emit_monitor_event(:connect_delayed, endpoint: endpoint)
|
|
228
227
|
schedule_reconnect(endpoint, delay: 0)
|
|
@@ -239,6 +238,7 @@ module OMQ
|
|
|
239
238
|
# @return [void]
|
|
240
239
|
#
|
|
241
240
|
def disconnect(endpoint)
|
|
241
|
+
endpoint = canonical_endpoint(endpoint)
|
|
242
242
|
@dialers.delete(endpoint)
|
|
243
243
|
close_connections_at(endpoint)
|
|
244
244
|
end
|
|
@@ -251,6 +251,7 @@ module OMQ
|
|
|
251
251
|
# @return [void]
|
|
252
252
|
#
|
|
253
253
|
def unbind(endpoint)
|
|
254
|
+
endpoint = canonical_endpoint(endpoint)
|
|
254
255
|
listener = @listeners.delete(endpoint) or return
|
|
255
256
|
|
|
256
257
|
listener.stop
|
|
@@ -608,8 +609,8 @@ module OMQ
|
|
|
608
609
|
# @raise [ArgumentError] if the scheme is not registered
|
|
609
610
|
#
|
|
610
611
|
def transport_for(endpoint)
|
|
611
|
-
scheme = endpoint
|
|
612
|
-
transport =
|
|
612
|
+
scheme = scheme_for(endpoint)
|
|
613
|
+
transport = registered_transport(scheme)
|
|
613
614
|
|
|
614
615
|
unless transport
|
|
615
616
|
raise ArgumentError, "unsupported transport: #{endpoint}"
|
|
@@ -701,15 +702,65 @@ module OMQ
|
|
|
701
702
|
# @param endpoint [String]
|
|
702
703
|
# @raise [ArgumentError] if the transport rejects the endpoint
|
|
703
704
|
#
|
|
704
|
-
def validate_endpoint!(endpoint)
|
|
705
|
-
transport = transport_for(endpoint)
|
|
706
|
-
|
|
705
|
+
def validate_endpoint!(endpoint, transport)
|
|
707
706
|
if transport.respond_to?(:validate_endpoint!)
|
|
708
707
|
transport.validate_endpoint!(endpoint)
|
|
709
708
|
end
|
|
710
709
|
end
|
|
711
710
|
|
|
712
711
|
|
|
712
|
+
# Resolves transport aliases before the endpoint is stored in
|
|
713
|
+
# listener, dialer, or connection maps.
|
|
714
|
+
#
|
|
715
|
+
# @param endpoint [String]
|
|
716
|
+
# @return [Array(String, Module)]
|
|
717
|
+
#
|
|
718
|
+
def resolve_endpoint(endpoint)
|
|
719
|
+
transport = transport_for(endpoint)
|
|
720
|
+
if transport.respond_to?(:canonical_endpoint)
|
|
721
|
+
endpoint = transport.canonical_endpoint(endpoint)
|
|
722
|
+
end
|
|
723
|
+
|
|
724
|
+
[endpoint, transport]
|
|
725
|
+
end
|
|
726
|
+
|
|
727
|
+
|
|
728
|
+
# Best-effort normalization for disconnect/unbind. Unknown schemes
|
|
729
|
+
# stay as-is so those calls remain no-ops instead of raising.
|
|
730
|
+
#
|
|
731
|
+
# @param endpoint [String]
|
|
732
|
+
# @return [String]
|
|
733
|
+
#
|
|
734
|
+
def canonical_endpoint(endpoint)
|
|
735
|
+
transport = registered_transport(scheme_for(endpoint))
|
|
736
|
+
return endpoint unless transport&.respond_to?(:canonical_endpoint)
|
|
737
|
+
|
|
738
|
+
transport.canonical_endpoint(endpoint)
|
|
739
|
+
end
|
|
740
|
+
|
|
741
|
+
|
|
742
|
+
# Looks up a registered transport. If no real inproc transport is
|
|
743
|
+
# registered, inproc:// falls back to the Ruby in-process transport.
|
|
744
|
+
#
|
|
745
|
+
# @param scheme [String, nil]
|
|
746
|
+
# @return [Module, nil]
|
|
747
|
+
#
|
|
748
|
+
def registered_transport(scheme)
|
|
749
|
+
self.class.transports[scheme] ||
|
|
750
|
+
(scheme == "inproc" ? self.class.transports["ruby"] : nil)
|
|
751
|
+
end
|
|
752
|
+
|
|
753
|
+
|
|
754
|
+
# Extracts the URI scheme from an endpoint.
|
|
755
|
+
#
|
|
756
|
+
# @param endpoint [String]
|
|
757
|
+
# @return [String, nil]
|
|
758
|
+
#
|
|
759
|
+
def scheme_for(endpoint)
|
|
760
|
+
endpoint[/\A([^:]+):\/\//, 1]
|
|
761
|
+
end
|
|
762
|
+
|
|
763
|
+
|
|
713
764
|
# Starts the listener's accept loops on the socket-level barrier
|
|
714
765
|
# and routes accepted IOs through {#handle_accepted}.
|
|
715
766
|
#
|
data/lib/omq/socket.rb
CHANGED
data/lib/omq/transport/inproc.rb
CHANGED
|
@@ -13,8 +13,8 @@ module OMQ
|
|
|
13
13
|
# serialization. Parts are already frozen by Writable#send, so the
|
|
14
14
|
# receiver sees the same immutable contract as ZMTP transports.
|
|
15
15
|
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
16
|
+
# inproc:// is treated as a compatibility alias by the Ruby backend
|
|
17
|
+
# unless a backend or plugin registers a real inproc transport.
|
|
18
18
|
#
|
|
19
19
|
module Inproc
|
|
20
20
|
Engine.transports["ruby"] = self
|
|
@@ -38,6 +38,17 @@ module OMQ
|
|
|
38
38
|
attr_reader :registry
|
|
39
39
|
|
|
40
40
|
|
|
41
|
+
# Canonicalizes compatibility aliases so ruby:// and inproc://
|
|
42
|
+
# share the same in-process endpoint namespace.
|
|
43
|
+
#
|
|
44
|
+
# @param endpoint [String]
|
|
45
|
+
# @return [String]
|
|
46
|
+
#
|
|
47
|
+
def canonical_endpoint(endpoint)
|
|
48
|
+
endpoint.sub(/\Ainproc:\/\//, "ruby://")
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
|
|
41
52
|
# Creates a bound inproc listener.
|
|
42
53
|
#
|
|
43
54
|
# @param endpoint [String] e.g. "ruby://my-endpoint"
|
|
@@ -46,6 +57,8 @@ module OMQ
|
|
|
46
57
|
# @raise [ArgumentError] if endpoint is already bound
|
|
47
58
|
#
|
|
48
59
|
def listener(endpoint, engine, **)
|
|
60
|
+
endpoint = canonical_endpoint(endpoint)
|
|
61
|
+
|
|
49
62
|
@mutex.synchronize do
|
|
50
63
|
if @registry.key?(endpoint)
|
|
51
64
|
raise ArgumentError, "endpoint already bound: #{endpoint}"
|
|
@@ -68,6 +81,7 @@ module OMQ
|
|
|
68
81
|
# @return [void]
|
|
69
82
|
#
|
|
70
83
|
def connect(endpoint, engine, **)
|
|
84
|
+
endpoint = canonical_endpoint(endpoint)
|
|
71
85
|
bound_engine = @mutex.synchronize { @registry[endpoint] }
|
|
72
86
|
bound_engine ||= await_bind(endpoint, engine) or return
|
|
73
87
|
establish_link(engine, bound_engine, endpoint)
|
|
@@ -80,6 +94,7 @@ module OMQ
|
|
|
80
94
|
# @return [void]
|
|
81
95
|
#
|
|
82
96
|
def unbind(endpoint)
|
|
97
|
+
endpoint = canonical_endpoint(endpoint)
|
|
83
98
|
@mutex.synchronize { @registry.delete(endpoint) }
|
|
84
99
|
end
|
|
85
100
|
|
data/lib/omq/version.rb
CHANGED