omq-rs 0.1.0 → 0.1.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 +4 -4
- data/CHANGELOG.md +11 -0
- data/DEVELOPMENT.md +170 -0
- data/README.md +11 -24
- data/ext/omq_rs_native/Cargo.toml +3 -3
- data/ext/omq_rs_native/src/socket.rs +4 -2
- data/lib/omq/rs/socket.rb +143 -5
- data/lib/omq/rs/version.rb +1 -1
- data/lib/omq/rs.rb +1 -0
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 529730a7fd3a4fe212f423bd4404fe12d5b33818cc2ec80df6e971183464f98f
|
|
4
|
+
data.tar.gz: 6af2f40b2a2a3dda39d761b6125df5c0d7eb252e0928725caed653d2bfa8f5e4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3704feceb32e6e3765de1c5450f0151e96a578ecfc8f6b1ae14a4e024eab25e700f88ae4c39dca36e259471993658e8ba4505d607a51843e60e87dbe83215770
|
|
7
|
+
data.tar.gz: 1e936ad84a6292b4a4f3a66ab64cc926a71095d136425fe640c67bfe051a73456199ba6bf59d3fa909248fc1591e2fb7afb4a16726e30100b9283aec0caeec09
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.1.1] - 2026-08-23
|
|
6
|
+
|
|
7
|
+
- Document the full public API and publish the RubyDoc documentation link.
|
|
8
|
+
- Reject unknown socket options instead of silently ignoring misspellings.
|
|
9
|
+
- Make peer, subscriber, and monitor waits stop cleanly when a socket closes.
|
|
10
|
+
- Release the CURVE auth-worker mutex before joining its thread during close.
|
|
11
|
+
- Add mixed transport, protocol, lifecycle, and resource soak coverage.
|
|
12
|
+
- Require `omq-proto` 0.26.1 and `omq-tokio` 0.21.4.
|
|
13
|
+
|
|
14
|
+
## [0.1.0] - 2026-08-20
|
|
15
|
+
|
|
5
16
|
- Add standalone `omq-rs` Ruby binding with all 20 OMQ socket types.
|
|
6
17
|
- Add PLAIN and CURVE sockets, Z85 key generation, CURVE client authentication,
|
|
7
18
|
and pyzmq CURVE interoperability.
|
data/DEVELOPMENT.md
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# omq-rs development
|
|
2
|
+
|
|
3
|
+
Run commands from the repository root unless a section changes directory.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- Ruby 3.3 or newer with Bundler.
|
|
8
|
+
- Rust 1.93 or newer with Cargo, rustfmt, and Clippy.
|
|
9
|
+
- Python with pyzmq for the Python interoperability tests.
|
|
10
|
+
- CZMQ and libzmq development files for cztop interoperability and both
|
|
11
|
+
benchmark baselines.
|
|
12
|
+
|
|
13
|
+
Install the Ruby dependencies:
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
cd bindings/ruby
|
|
17
|
+
bundle install
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Build and test
|
|
21
|
+
|
|
22
|
+
Run the normal binding test pass from the repository root:
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
./scripts/test-ruby.sh
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Select a Ruby executable explicitly with `OMQ_RUBY`:
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
OMQ_RUBY=/path/to/ruby ./scripts/test-ruby.sh
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The equivalent commands from the binding directory are:
|
|
35
|
+
|
|
36
|
+
```sh
|
|
37
|
+
cd bindings/ruby
|
|
38
|
+
bundle exec rake
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Compile once, then run one test file:
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
bundle exec rake compile
|
|
45
|
+
bundle exec ruby -Ilib:test test/test_features.rb
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The suite covers socket patterns, options, transports, CURVE, PLAIN,
|
|
49
|
+
compression, monitors, Fiber schedulers, Ractors, lifecycle behavior, and
|
|
50
|
+
pyzmq interoperability. pyzmq tests skip when pyzmq is unavailable. cztop
|
|
51
|
+
tests skip when CZMQ or cztop is unavailable. Ractor tests require Ruby 4.
|
|
52
|
+
|
|
53
|
+
## Soak tests
|
|
54
|
+
|
|
55
|
+
Run the mixed transport, security, compression, churn, and resource soak:
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
bindings/ruby/scripts/soak.sh 1h
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The duration accepts `s`, `m`, `h`, or `d`. The test reports progress, RSS,
|
|
62
|
+
file descriptors, and Ruby thread counts. It fails on message corruption,
|
|
63
|
+
stalls, or sustained resource growth.
|
|
64
|
+
|
|
65
|
+
`scripts/test-all.sh` includes the Ruby pass in the full repository test run.
|
|
66
|
+
|
|
67
|
+
## Static checks
|
|
68
|
+
|
|
69
|
+
Run the same native checks as CI:
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
cargo fmt --manifest-path bindings/ruby/Cargo.toml --all --check
|
|
73
|
+
cargo clippy --manifest-path bindings/ruby/Cargo.toml \
|
|
74
|
+
--all-targets --all-features -- -D warnings
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Check Ruby syntax:
|
|
78
|
+
|
|
79
|
+
```sh
|
|
80
|
+
find bindings/ruby/lib bindings/ruby/test bindings/ruby/scripts \
|
|
81
|
+
-name '*.rb' -print0 | xargs -0 -n1 ruby -cw
|
|
82
|
+
ruby -cw bindings/ruby/Rakefile
|
|
83
|
+
ruby -cw bindings/ruby/omq-rs.gemspec
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Check public YARD coverage from `bindings/ruby` after installing YARD:
|
|
87
|
+
|
|
88
|
+
```sh
|
|
89
|
+
yard stats --no-save --no-cache --list-undoc --no-private \
|
|
90
|
+
'lib/**/*.rb' 'lib/*.rb'
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Benchmarks
|
|
94
|
+
|
|
95
|
+
Run benchmarks on an otherwise idle machine. The harness starts separate Ruby
|
|
96
|
+
processes over TCP. PUSH/PULL throughput covers 16 B through 32 KiB. REQ/REP
|
|
97
|
+
mean latency covers 16 B through 4 KiB. The default run keeps the median of three
|
|
98
|
+
rounds for each implementation, pattern, and message size. Throughput uses a
|
|
99
|
+
0.5 second warmup and 2.5 second measurement window. Latency uses a 0.5 second
|
|
100
|
+
warmup and 1.5 second measurement window.
|
|
101
|
+
|
|
102
|
+
From the binding directory:
|
|
103
|
+
|
|
104
|
+
```sh
|
|
105
|
+
cd bindings/ruby
|
|
106
|
+
bundle exec rake compile
|
|
107
|
+
bundle exec ruby -Ilib scripts/update_perf.rb
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The default run benchmarks `omq-rs`. It includes cztop when CZMQ is available
|
|
111
|
+
and ffi-rzmq when libzmq is available. Missing baselines are skipped.
|
|
112
|
+
|
|
113
|
+
Useful controls:
|
|
114
|
+
|
|
115
|
+
```sh
|
|
116
|
+
bundle exec ruby -Ilib scripts/update_perf.rb --quick
|
|
117
|
+
bundle exec ruby -Ilib scripts/update_perf.rb --impl omq-rs,cztop,ffi-rzmq
|
|
118
|
+
bundle exec ruby -Ilib scripts/update_perf.rb --patterns pushpull,reqrep
|
|
119
|
+
bundle exec ruby -Ilib scripts/update_perf.rb --sizes 16,128,1024,4096
|
|
120
|
+
bundle exec ruby -Ilib scripts/update_perf.rb --rounds 5
|
|
121
|
+
bundle exec ruby -Ilib scripts/update_perf.rb --duration 2.5 --warmup-duration 0.5
|
|
122
|
+
bundle exec ruby -Ilib scripts/update_perf.rb --latency-duration 1.5 --latency-warmup-duration 0.5
|
|
123
|
+
bundle exec ruby -Ilib scripts/update_perf.rb --no-record
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
`--quick` runs one round at 128 B and 1 KiB without recording results or
|
|
127
|
+
rewriting the chart.
|
|
128
|
+
|
|
129
|
+
## Chart generation
|
|
130
|
+
|
|
131
|
+
Benchmark rows append to:
|
|
132
|
+
|
|
133
|
+
```text
|
|
134
|
+
~/.cache/omq-rs/bindings.jsonl
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Regenerate the SVG from the latest cached row for each implementation,
|
|
138
|
+
pattern, and message size:
|
|
139
|
+
|
|
140
|
+
```sh
|
|
141
|
+
cd bindings/ruby
|
|
142
|
+
bundle exec ruby -Ilib scripts/update_perf.rb --chart-only
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The output is `bindings/ruby/doc/charts/bindings.svg`. Its hardware subtitle
|
|
146
|
+
comes from the repository-root `.chart_hw` file:
|
|
147
|
+
|
|
148
|
+
```text
|
|
149
|
+
prefix=Linux VM on a 2018 Mac Mini
|
|
150
|
+
postfix=6 cores, performance governor, turbo off
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
`.chart_hw` is local-only and gitignored.
|
|
154
|
+
|
|
155
|
+
## Packaging and release
|
|
156
|
+
|
|
157
|
+
Build the source gem from the binding directory:
|
|
158
|
+
|
|
159
|
+
```sh
|
|
160
|
+
cd bindings/ruby
|
|
161
|
+
bundle exec rake build
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
The gem is written to `bindings/ruby/pkg/`. Publication runs only through
|
|
165
|
+
`.github/workflows/release-rubygems.yml` using RubyGems trusted publishing.
|
|
166
|
+
The release tag must match the gem version:
|
|
167
|
+
|
|
168
|
+
```text
|
|
169
|
+
ruby-v<VERSION>
|
|
170
|
+
```
|
data/README.md
CHANGED
|
@@ -7,6 +7,16 @@ synchronous; its waits cooperate with an installed `Fiber.scheduler`.
|
|
|
7
7
|
MRI 3.3+, MRI 4.0+, and TruffleRuby are supported. TruffleRuby 34 does not
|
|
8
8
|
provide Ruby's `Fiber.scheduler` API, so waits block the calling thread there.
|
|
9
9
|
|
|
10
|
+
## Performance
|
|
11
|
+
|
|
12
|
+

|
|
13
|
+
|
|
14
|
+
The binding benchmark uses separate Ruby processes over TCP and compares
|
|
15
|
+
`omq-rs` with [cztop](https://github.com/paddor/cztop), which calls CZMQ and
|
|
16
|
+
libzmq through FFI, and [ffi-rzmq](https://github.com/chuckremes/ffi-rzmq),
|
|
17
|
+
which calls libzmq directly through FFI. See [DEVELOPMENT.md](DEVELOPMENT.md)
|
|
18
|
+
for methodology and regeneration commands.
|
|
19
|
+
|
|
10
20
|
## Install
|
|
11
21
|
|
|
12
22
|
```sh
|
|
@@ -131,30 +141,7 @@ TCP endpoints; no preparation call is required.
|
|
|
131
141
|
|
|
132
142
|
## Development
|
|
133
143
|
|
|
134
|
-
|
|
135
|
-
bundle install
|
|
136
|
-
bundle exec rake
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
## Performance
|
|
140
|
-
|
|
141
|
-

|
|
142
|
-
|
|
143
|
-
The binding benchmark uses separate Ruby processes over TCP and compares
|
|
144
|
-
`omq-rs` with [cztop](https://github.com/paddor/cztop), which calls CZMQ and
|
|
145
|
-
libzmq through FFI, and [ffi-rzmq](https://github.com/chuckremes/ffi-rzmq),
|
|
146
|
-
which calls libzmq directly through FFI. Install CZMQ and libzmq to include
|
|
147
|
-
both baselines.
|
|
148
|
-
|
|
149
|
-
```sh
|
|
150
|
-
ruby -Ilib scripts/update_perf.rb
|
|
151
|
-
ruby -Ilib scripts/update_perf.rb --quick
|
|
152
|
-
ruby -Ilib scripts/update_perf.rb --chart-only
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
Rows append to `~/.cache/omq-rs/bindings.jsonl`. The generated chart is
|
|
156
|
-
`doc/charts/bindings.svg`. `--quick` only runs a smoke benchmark and does not
|
|
157
|
-
write results or a chart.
|
|
144
|
+
Build, test, benchmark, and release instructions: [DEVELOPMENT.md](DEVELOPMENT.md).
|
|
158
145
|
|
|
159
146
|
## License
|
|
160
147
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "omq_rs_native"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.1"
|
|
4
4
|
edition = "2024"
|
|
5
5
|
rust-version = "1.93"
|
|
6
6
|
license = "ISC"
|
|
@@ -20,8 +20,8 @@ zstd = ["omq-tokio/zstd"]
|
|
|
20
20
|
ws = ["omq-tokio/ws"]
|
|
21
21
|
|
|
22
22
|
[dependencies]
|
|
23
|
-
omq-proto = { version = ">=0.26.
|
|
24
|
-
omq-tokio = { version = ">=0.21.
|
|
23
|
+
omq-proto = { version = ">=0.26.1, <0.28.0", default-features = false }
|
|
24
|
+
omq-tokio = { version = ">=0.21.4, <0.23.0", default-features = false }
|
|
25
25
|
yring = { version = "=0.3.14", features = ["async"] }
|
|
26
26
|
|
|
27
27
|
bytes = "1.12.0"
|
|
@@ -198,7 +198,8 @@ fn set_curve_authenticator(
|
|
|
198
198
|
}
|
|
199
199
|
drop(options_guard);
|
|
200
200
|
|
|
201
|
-
|
|
201
|
+
let previous = rb_self.auth_worker.lock().unwrap().take();
|
|
202
|
+
if let Some(previous) = previous {
|
|
202
203
|
previous.stop();
|
|
203
204
|
}
|
|
204
205
|
*rb_self.auth_worker.lock().unwrap() = worker;
|
|
@@ -774,7 +775,8 @@ unsafe extern "C" fn rust_socket_leave(rb_self: VALUE, group: VALUE) -> VALUE {
|
|
|
774
775
|
fn rust_socket_close_impl(rb_self: &RustSocket, wait_for_auth_worker: bool) {
|
|
775
776
|
rb_self.closed.store(true, Ordering::Relaxed);
|
|
776
777
|
#[cfg(feature = "curve")]
|
|
777
|
-
|
|
778
|
+
let worker = rb_self.auth_worker.lock().unwrap().take();
|
|
779
|
+
if let Some(worker) = worker {
|
|
778
780
|
if wait_for_auth_worker {
|
|
779
781
|
worker.stop();
|
|
780
782
|
} else {
|
data/lib/omq/rs/socket.rb
CHANGED
|
@@ -18,6 +18,69 @@ module OMQ
|
|
|
18
18
|
# @api private
|
|
19
19
|
SINGLE_FRAME_TYPES = %i[client server scatter gather channel].freeze
|
|
20
20
|
|
|
21
|
+
# @api private
|
|
22
|
+
SOCKET_OPTIONS = %w[
|
|
23
|
+
workload_profile
|
|
24
|
+
send_hwm
|
|
25
|
+
recv_hwm
|
|
26
|
+
recv_rate_limit
|
|
27
|
+
recv_ip_rate_limit
|
|
28
|
+
|
|
29
|
+
linger
|
|
30
|
+
identity
|
|
31
|
+
router_mandatory
|
|
32
|
+
conflate
|
|
33
|
+
|
|
34
|
+
heartbeat_interval
|
|
35
|
+
heartbeat_ttl
|
|
36
|
+
heartbeat_timeout
|
|
37
|
+
handshake_timeout
|
|
38
|
+
max_pending_handshakes
|
|
39
|
+
|
|
40
|
+
max_message_size
|
|
41
|
+
sndbuf
|
|
42
|
+
rcvbuf
|
|
43
|
+
large_message_threshold
|
|
44
|
+
arena_threshold
|
|
45
|
+
transmit_slot_cap
|
|
46
|
+
|
|
47
|
+
xpub_nodrop
|
|
48
|
+
reconnect_stop_conn_refused
|
|
49
|
+
on_mute
|
|
50
|
+
reconnect_interval
|
|
51
|
+
reconnect_interval_min
|
|
52
|
+
reconnect_interval_max
|
|
53
|
+
|
|
54
|
+
compression_dict
|
|
55
|
+
compression_auto_train
|
|
56
|
+
compression_threshold
|
|
57
|
+
compression_level
|
|
58
|
+
compression_dict_capacity
|
|
59
|
+
max_recv_dict_size
|
|
60
|
+
compression_offload_threshold
|
|
61
|
+
|
|
62
|
+
mechanism_type
|
|
63
|
+
mechanism_server
|
|
64
|
+
mechanism_public_key
|
|
65
|
+
mechanism_secret_key
|
|
66
|
+
mechanism_server_key
|
|
67
|
+
mechanism_username
|
|
68
|
+
mechanism_password
|
|
69
|
+
|
|
70
|
+
curve_server
|
|
71
|
+
curve_publickey
|
|
72
|
+
curve_public_key
|
|
73
|
+
curve_secretkey
|
|
74
|
+
curve_secret_key
|
|
75
|
+
curve_serverkey
|
|
76
|
+
curve_server_key
|
|
77
|
+
|
|
78
|
+
plain_server
|
|
79
|
+
plain_username
|
|
80
|
+
plain_password
|
|
81
|
+
].freeze
|
|
82
|
+
private_constant :ROUTED_TYPES, :SINGLE_FRAME_TYPES, :SOCKET_OPTIONS
|
|
83
|
+
|
|
21
84
|
# CURVE peer metadata passed to callable authenticators.
|
|
22
85
|
#
|
|
23
86
|
# @!attribute [r] public_key
|
|
@@ -34,11 +97,13 @@ module OMQ
|
|
|
34
97
|
Native.io_threads
|
|
35
98
|
end
|
|
36
99
|
|
|
37
|
-
# Sets number of OMQ.rs IO threads
|
|
100
|
+
# Sets number of OMQ.rs IO threads before the shared runtime starts.
|
|
38
101
|
#
|
|
39
102
|
# @param count [Integer] positive IO thread count
|
|
40
103
|
# @return [Integer] assigned count
|
|
41
104
|
# @raise [ArgumentError] if +count+ is not positive
|
|
105
|
+
# @note Set this before materializing any socket. It does not resize a
|
|
106
|
+
# running runtime.
|
|
42
107
|
def io_threads=(count)
|
|
43
108
|
count = Integer(count)
|
|
44
109
|
raise ArgumentError, "io_threads must be positive" unless count.positive?
|
|
@@ -139,7 +204,9 @@ module OMQ
|
|
|
139
204
|
def each
|
|
140
205
|
return enum_for(__method__) unless block_given?
|
|
141
206
|
|
|
142
|
-
|
|
207
|
+
while (event = recv)
|
|
208
|
+
yield event
|
|
209
|
+
end
|
|
143
210
|
rescue IOError
|
|
144
211
|
raise unless @socket.closed?
|
|
145
212
|
end
|
|
@@ -156,8 +223,53 @@ module OMQ
|
|
|
156
223
|
# @param send_timeout [Numeric, nil] send timeout in seconds
|
|
157
224
|
# @param curve_auth [Array<String>, #call, nil] CURVE allowlist or authenticator
|
|
158
225
|
# @param options [Hash] native OMQ.rs socket options
|
|
226
|
+
# @option options [Symbol] :workload_profile +:throughput+ or +:latency+
|
|
227
|
+
# @option options [Integer] :send_hwm outbound message capacity
|
|
228
|
+
# @option options [Integer] :recv_hwm inbound message capacity
|
|
229
|
+
# @option options [Hash] :recv_rate_limit per-connection
|
|
230
|
+
# +:messages_per_second+ (or +:rate+) and +:burst+
|
|
231
|
+
# @option options [Hash] :recv_ip_rate_limit per-IP
|
|
232
|
+
# +:messages_per_second+ (or +:rate+) and +:burst+
|
|
233
|
+
# @option options [Numeric] :linger close linger in seconds; positive
|
|
234
|
+
# infinity waits forever
|
|
235
|
+
# @option options [String] :identity ZMTP socket identity
|
|
236
|
+
# @option options [Boolean] :router_mandatory reject unroutable sends
|
|
237
|
+
# @option options [Boolean] :conflate retain only latest received message
|
|
238
|
+
# @option options [Numeric] :heartbeat_interval heartbeat period in seconds
|
|
239
|
+
# @option options [Numeric] :heartbeat_ttl remote heartbeat TTL in seconds
|
|
240
|
+
# @option options [Numeric] :heartbeat_timeout peer timeout in seconds
|
|
241
|
+
# @option options [Numeric] :handshake_timeout handshake timeout in seconds
|
|
242
|
+
# @option options [Integer] :max_pending_handshakes inbound handshake limit
|
|
243
|
+
# @option options [Integer] :max_message_size maximum received message bytes
|
|
244
|
+
# @option options [Integer] :sndbuf kernel send buffer bytes
|
|
245
|
+
# @option options [Integer] :rcvbuf kernel receive buffer bytes
|
|
246
|
+
# @option options [Integer] :large_message_threshold receive buffer threshold
|
|
247
|
+
# @option options [Integer] :arena_threshold contiguous frame arena threshold
|
|
248
|
+
# @option options [Integer] :transmit_slot_cap per-peer transmit bytes
|
|
249
|
+
# @option options [Boolean] :xpub_nodrop block instead of dropping on mute
|
|
250
|
+
# @option options [Boolean] :reconnect_stop_conn_refused stop refused reconnects
|
|
251
|
+
# @option options [Symbol] :on_mute +:block+, +:drop_newest+, or +:drop_oldest+
|
|
252
|
+
# @option options [Numeric] :reconnect_interval fixed reconnect delay in seconds
|
|
253
|
+
# @option options [Numeric] :reconnect_interval_min minimum backoff in seconds
|
|
254
|
+
# @option options [Numeric] :reconnect_interval_max maximum backoff in seconds
|
|
255
|
+
# @option options [String] :compression_dict compression dictionary bytes
|
|
256
|
+
# @option options [Boolean] :compression_auto_train train a zstd dictionary
|
|
257
|
+
# @option options [Integer] :compression_threshold minimum bytes to compress
|
|
258
|
+
# @option options [Integer] :compression_level zstd compression level
|
|
259
|
+
# @option options [Integer] :compression_dict_capacity trained dictionary bytes
|
|
260
|
+
# @option options [Integer] :max_recv_dict_size received dictionary byte limit
|
|
261
|
+
# @option options [Integer] :compression_offload_threshold offload threshold;
|
|
262
|
+
# negative disables offloading
|
|
263
|
+
# @option options [Symbol] :mechanism_type +:null+, +:plain+, or +:curve+
|
|
264
|
+
# @option options [Boolean] :plain_server enable PLAIN server mode
|
|
265
|
+
# @option options [String] :plain_username PLAIN client username
|
|
266
|
+
# @option options [String] :plain_password PLAIN client password
|
|
267
|
+
# @option options [Boolean] :curve_server enable CURVE server mode
|
|
268
|
+
# @option options [String] :curve_publickey local raw or Z85 public key
|
|
269
|
+
# @option options [String] :curve_secretkey local raw or Z85 secret key
|
|
270
|
+
# @option options [String] :curve_serverkey CURVE server raw or Z85 public key
|
|
159
271
|
# @return [Socket]
|
|
160
|
-
# @raise [ArgumentError] if an option is invalid
|
|
272
|
+
# @raise [ArgumentError] if an option is unknown or invalid
|
|
161
273
|
def initialize(recv_timeout: nil, send_timeout: nil, curve_auth: nil, **options)
|
|
162
274
|
socket_type = self.class.const_get(:SOCKET_TYPE, false)
|
|
163
275
|
@socket_type = socket_type.to_s.downcase.to_sym
|
|
@@ -176,6 +288,8 @@ module OMQ
|
|
|
176
288
|
@materialized = false
|
|
177
289
|
@recv_io = nil
|
|
178
290
|
@send_io = nil
|
|
291
|
+
@peer_connected = false
|
|
292
|
+
@subscriber_joined = false
|
|
179
293
|
set_curve_auth(curve_auth) unless curve_auth.nil?
|
|
180
294
|
end
|
|
181
295
|
|
|
@@ -228,7 +342,7 @@ module OMQ
|
|
|
228
342
|
@native.peer_info(routing_id)
|
|
229
343
|
end
|
|
230
344
|
|
|
231
|
-
# Configures CURVE client
|
|
345
|
+
# Configures CURVE client authorization on a server before materialization.
|
|
232
346
|
#
|
|
233
347
|
# @param authenticator [Array<String>, #call, nil] public-key allowlist,
|
|
234
348
|
# callable receiving {MechanismPeerInfo}, or +nil+ to allow valid clients
|
|
@@ -430,9 +544,16 @@ module OMQ
|
|
|
430
544
|
# @param timeout [Numeric, nil] maximum wait in seconds
|
|
431
545
|
# @return [Socket] self
|
|
432
546
|
# @raise [IO::TimeoutError] if timeout expires
|
|
547
|
+
# @raise [IOError] if socket closes first
|
|
433
548
|
def wait_for_peer(timeout: nil)
|
|
549
|
+
raise IOError, "socket closed" if closed?
|
|
550
|
+
return self if @peer_connected
|
|
551
|
+
|
|
434
552
|
ensure_materialized
|
|
435
553
|
wait_for_native_fd(@native.peer_connected_fd, timeout, "peer connection timed out")
|
|
554
|
+
raise IOError, "socket closed" if closed?
|
|
555
|
+
|
|
556
|
+
@peer_connected = true
|
|
436
557
|
self
|
|
437
558
|
end
|
|
438
559
|
|
|
@@ -441,9 +562,16 @@ module OMQ
|
|
|
441
562
|
# @param timeout [Numeric, nil] maximum wait in seconds
|
|
442
563
|
# @return [Socket] self
|
|
443
564
|
# @raise [IO::TimeoutError] if timeout expires
|
|
565
|
+
# @raise [IOError] if socket closes first
|
|
444
566
|
def wait_for_subscriber(timeout: nil)
|
|
567
|
+
raise IOError, "socket closed" if closed?
|
|
568
|
+
return self if @subscriber_joined
|
|
569
|
+
|
|
445
570
|
ensure_materialized
|
|
446
571
|
wait_for_native_fd(@native.subscriber_joined_fd, timeout, "subscriber timed out")
|
|
572
|
+
raise IOError, "socket closed" if closed?
|
|
573
|
+
|
|
574
|
+
@subscriber_joined = true
|
|
447
575
|
self
|
|
448
576
|
end
|
|
449
577
|
|
|
@@ -471,6 +599,8 @@ module OMQ
|
|
|
471
599
|
# @return [Hash, nil]
|
|
472
600
|
# @raise [IO::TimeoutError] if timeout expires
|
|
473
601
|
def monitor_event(timeout: @recv_timeout)
|
|
602
|
+
return if closed?
|
|
603
|
+
|
|
474
604
|
ensure_materialized
|
|
475
605
|
event = @native.try_recv_monitor
|
|
476
606
|
return event if event
|
|
@@ -483,6 +613,8 @@ module OMQ
|
|
|
483
613
|
#
|
|
484
614
|
# @return [Hash, nil]
|
|
485
615
|
def try_monitor_event
|
|
616
|
+
return if closed?
|
|
617
|
+
|
|
486
618
|
ensure_materialized
|
|
487
619
|
@native.try_recv_monitor
|
|
488
620
|
end
|
|
@@ -532,11 +664,17 @@ module OMQ
|
|
|
532
664
|
end
|
|
533
665
|
|
|
534
666
|
def normalize_options(options)
|
|
535
|
-
options.to_h do |key, value|
|
|
667
|
+
normalized = options.to_h do |key, value|
|
|
536
668
|
value = value.to_s if value.is_a?(Symbol)
|
|
537
669
|
value = value.transform_keys(&:to_s) if value.is_a?(Hash)
|
|
538
670
|
[key.to_s, value]
|
|
539
671
|
end
|
|
672
|
+
unknown = normalized.keys - SOCKET_OPTIONS
|
|
673
|
+
unless unknown.empty?
|
|
674
|
+
raise ArgumentError, "unknown socket option#{"s" if unknown.length > 1}: #{unknown.sort.join(", ")}"
|
|
675
|
+
end
|
|
676
|
+
|
|
677
|
+
normalized
|
|
540
678
|
end
|
|
541
679
|
|
|
542
680
|
def validate_send_parts!(parts)
|
data/lib/omq/rs/version.rb
CHANGED
data/lib/omq/rs.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: omq-rs
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Patrik Wenger
|
|
@@ -33,6 +33,7 @@ extensions:
|
|
|
33
33
|
extra_rdoc_files: []
|
|
34
34
|
files:
|
|
35
35
|
- CHANGELOG.md
|
|
36
|
+
- DEVELOPMENT.md
|
|
36
37
|
- LICENSE
|
|
37
38
|
- README.md
|
|
38
39
|
- ext/omq_rs_native/Cargo.toml
|
|
@@ -56,6 +57,7 @@ licenses:
|
|
|
56
57
|
metadata:
|
|
57
58
|
source_code_uri: https://github.com/paddor/omq.rs/tree/main/bindings/ruby
|
|
58
59
|
changelog_uri: https://github.com/paddor/omq.rs/tree/main/bindings/ruby/CHANGELOG.md
|
|
60
|
+
documentation_uri: https://www.rubydoc.info/gems/omq-rs
|
|
59
61
|
rubygems_mfa_required: 'true'
|
|
60
62
|
rdoc_options: []
|
|
61
63
|
require_paths:
|