omq-backend-rust 0.1.5 → 0.1.6
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 +10 -0
- data/README.md +12 -0
- data/ext/omq_backend_rust/Cargo.toml +5 -4
- data/ext/omq_backend_rust/src/options.rs +23 -0
- data/lib/omq/rust/engine.rb +88 -2
- data/lib/omq/rust/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: a08620eb9fd1a781752e72f44186bbaee5fcefd37d92560901aa8fb7c6e4f269
|
|
4
|
+
data.tar.gz: 891cc692da98d5cd7e2daf2a461e06b4c7b41de91f88964d1d9f7cbc20616f9a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 37745e0ab15d9dabd1ec62262c821951ee489a6bc11f86eee30c355b9fff07909246800e2ac6184379d46bd958258c411a5be55fadaf052af92c7ef01d3e024f
|
|
7
|
+
data.tar.gz: 2b89190343754d64b322efa8cbb08f880900324247b87d7b0cbb4df6c5af195caa1da41d3909a32168e8f5ad12f3a82714648a43521e789ea70ff5b053c514c9
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.1.6] - 2026-08-01
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Updated to `omq-tokio` 0.20.3 and `omq-proto` 0.25.0.
|
|
10
|
+
- Enabled OMQ.rs `zstd+tcp://` by default.
|
|
11
|
+
- Forwarded compression bind/connect kwargs to current OMQ.rs options:
|
|
12
|
+
`dict:`, `auto_dict:`, `compression_threshold:`, `max_recv_dict_size:`,
|
|
13
|
+
`compression_offload_threshold:`, and zstd `level:`.
|
|
14
|
+
|
|
5
15
|
## [0.1.5] - 2026-07-31
|
|
6
16
|
|
|
7
17
|
### Fixed
|
data/README.md
CHANGED
|
@@ -58,6 +58,18 @@ SCATTER/GATHER, CHANNEL.
|
|
|
58
58
|
- **NULL** (default)
|
|
59
59
|
- **CURVE** (CurveZMQ, via [Nuckle](https://github.com/paddor/nuckle))
|
|
60
60
|
|
|
61
|
+
## Compressed transports
|
|
62
|
+
|
|
63
|
+
The Rust backend supports `lz4+tcp://` and `zstd+tcp://`. Compression
|
|
64
|
+
configuration uses the same bind/connect kwargs as the Ruby transports:
|
|
65
|
+
`level:` for zstd compression level (`-8..4`), `dict:` for a static
|
|
66
|
+
send-side dictionary, and `auto_dict: true` for automatic dictionary
|
|
67
|
+
training.
|
|
68
|
+
|
|
69
|
+
Automatic dictionary training is off by default.
|
|
70
|
+
OMQ.rs stores compression configuration per socket, so pass these kwargs on
|
|
71
|
+
the first `bind` or `connect` for a Rust-backed socket.
|
|
72
|
+
|
|
61
73
|
## Development
|
|
62
74
|
|
|
63
75
|
```sh
|
|
@@ -11,16 +11,17 @@ name = "omq_backend_rust"
|
|
|
11
11
|
crate-type = ["cdylib"]
|
|
12
12
|
|
|
13
13
|
[features]
|
|
14
|
-
default = ["plain", "curve", "lz4"]
|
|
14
|
+
default = ["plain", "curve", "lz4", "zstd"]
|
|
15
15
|
plain = ["omq-tokio/plain"]
|
|
16
16
|
curve = ["omq-tokio/curve"]
|
|
17
17
|
lz4 = ["omq-tokio/lz4"]
|
|
18
|
+
zstd = ["omq-tokio/zstd"]
|
|
18
19
|
|
|
19
20
|
[dependencies]
|
|
20
|
-
omq-proto = { version = "=0.
|
|
21
|
-
omq-tokio = { version = "=0.20.
|
|
21
|
+
omq-proto = { version = "=0.25.0", default-features = false }
|
|
22
|
+
omq-tokio = { version = "=0.20.3", default-features = false }
|
|
22
23
|
tokio = { version = "1.52.0", features = ["rt", "rt-multi-thread", "time", "sync", "io-util", "net"] }
|
|
23
|
-
yring = { version = "0.3.
|
|
24
|
+
yring = { version = "0.3.11", features = ["async"] }
|
|
24
25
|
|
|
25
26
|
bytes = "1.12.0"
|
|
26
27
|
flume = { version = "0.12", default-features = false, features = ["async"] }
|
|
@@ -48,6 +48,29 @@ pub fn build_options(ruby: &Ruby, hash: RHash) -> Result<omq_tokio::Options, Err
|
|
|
48
48
|
if let Some(v) = get_opt::<i64>(ruby, hash, "rcvbuf")? {
|
|
49
49
|
opts.recv_buffer_size = Some(v as usize);
|
|
50
50
|
}
|
|
51
|
+
if let Some(v) = get_opt_bytes(ruby, hash, "compression_dict")? {
|
|
52
|
+
if !v.is_empty() {
|
|
53
|
+
opts.compression_dict = Some(Bytes::from(v));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if let Some(v) = get_opt::<bool>(ruby, hash, "compression_auto_train")? {
|
|
57
|
+
opts.compression_auto_train = v;
|
|
58
|
+
}
|
|
59
|
+
if let Some(v) = get_opt::<i64>(ruby, hash, "compression_threshold")? {
|
|
60
|
+
opts.compression_threshold = Some(v as usize);
|
|
61
|
+
}
|
|
62
|
+
if let Some(v) = get_opt::<i64>(ruby, hash, "compression_level")? {
|
|
63
|
+
opts.compression_level = Some(v as i32);
|
|
64
|
+
}
|
|
65
|
+
if let Some(v) = get_opt::<i64>(ruby, hash, "compression_dict_capacity")? {
|
|
66
|
+
opts.compression_dict_capacity = Some(v as usize);
|
|
67
|
+
}
|
|
68
|
+
if let Some(v) = get_opt::<i64>(ruby, hash, "max_recv_dict_size")? {
|
|
69
|
+
opts.max_recv_dict_size = Some(v as usize);
|
|
70
|
+
}
|
|
71
|
+
if let Some(v) = get_opt::<i64>(ruby, hash, "compression_offload_threshold")? {
|
|
72
|
+
opts.compression_offload_threshold = if v < 0 { None } else { Some(v as usize) };
|
|
73
|
+
}
|
|
51
74
|
if let Some(v) = get_opt::<String>(ruby, hash, "on_mute")? {
|
|
52
75
|
opts.on_mute = match v.as_str() {
|
|
53
76
|
"drop_newest" | "drop" => omq_tokio::OnMute::DropNewest,
|
data/lib/omq/rust/engine.rb
CHANGED
|
@@ -25,6 +25,7 @@ module OMQ
|
|
|
25
25
|
@on_io_thread = false
|
|
26
26
|
@materialized = false
|
|
27
27
|
@recv_sentinels = 0
|
|
28
|
+
@compression_options = {}
|
|
28
29
|
|
|
29
30
|
@native = Native::RustSocket.new(socket_type.to_s)
|
|
30
31
|
|
|
@@ -47,16 +48,18 @@ module OMQ
|
|
|
47
48
|
end
|
|
48
49
|
|
|
49
50
|
|
|
50
|
-
def bind(endpoint, parent: nil, **)
|
|
51
|
+
def bind(endpoint, parent: nil, **opts)
|
|
51
52
|
capture_parent_task(parent: parent)
|
|
53
|
+
apply_endpoint_options!(opts)
|
|
52
54
|
ensure_materialized
|
|
53
55
|
resolved = @native.bind(endpoint)
|
|
54
56
|
URI.parse(resolved)
|
|
55
57
|
end
|
|
56
58
|
|
|
57
59
|
|
|
58
|
-
def connect(endpoint, parent: nil, **)
|
|
60
|
+
def connect(endpoint, parent: nil, **opts)
|
|
59
61
|
capture_parent_task(parent: parent)
|
|
62
|
+
apply_endpoint_options!(opts)
|
|
60
63
|
ensure_materialized
|
|
61
64
|
@native.connect(endpoint)
|
|
62
65
|
URI.parse(endpoint)
|
|
@@ -241,6 +244,7 @@ module OMQ
|
|
|
241
244
|
h["sndbuf"] = @options.sndbuf
|
|
242
245
|
h["rcvbuf"] = @options.rcvbuf
|
|
243
246
|
h["on_mute"] = @options.on_mute.to_s
|
|
247
|
+
h.merge!(@compression_options)
|
|
244
248
|
|
|
245
249
|
ri = @options.reconnect_interval
|
|
246
250
|
if ri.is_a?(Range)
|
|
@@ -256,6 +260,88 @@ module OMQ
|
|
|
256
260
|
end
|
|
257
261
|
|
|
258
262
|
|
|
263
|
+
def apply_endpoint_options!(opts)
|
|
264
|
+
compression = extract_endpoint_compression_options(opts)
|
|
265
|
+
return if compression.empty?
|
|
266
|
+
|
|
267
|
+
if @materialized
|
|
268
|
+
existing = compression.keys.to_h do |key|
|
|
269
|
+
[key, @compression_options.fetch(key, default_compression_option(key))]
|
|
270
|
+
end
|
|
271
|
+
return if compression == existing
|
|
272
|
+
|
|
273
|
+
raise ArgumentError,
|
|
274
|
+
"Rust backend compression options must be set before first bind/connect"
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
@compression_options.merge!(compression)
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
def extract_endpoint_compression_options(opts)
|
|
282
|
+
out = {}
|
|
283
|
+
|
|
284
|
+
if opts.key?(:level)
|
|
285
|
+
validate_zstd_level!(opts[:level])
|
|
286
|
+
out["compression_level"] = opts[:level]
|
|
287
|
+
end
|
|
288
|
+
out["compression_dict"] = opts[:dict].b if opts.key?(:dict) && opts[:dict]
|
|
289
|
+
|
|
290
|
+
if opts.key?(:auto_dict)
|
|
291
|
+
auto_dict = opts[:auto_dict]
|
|
292
|
+
if auto_dict && opts[:dict]
|
|
293
|
+
raise ArgumentError, "cannot combine auto_dict: and dict:"
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
case auto_dict
|
|
297
|
+
when nil, false
|
|
298
|
+
out["compression_auto_train"] = false
|
|
299
|
+
when true
|
|
300
|
+
out["compression_auto_train"] = true
|
|
301
|
+
when Hash
|
|
302
|
+
if auto_dict.key?(:trigger)
|
|
303
|
+
raise ArgumentError,
|
|
304
|
+
"Rust backend does not support auto_dict: trigger"
|
|
305
|
+
end
|
|
306
|
+
validate_positive!("auto_dict capacity", auto_dict[:capacity]) if auto_dict[:capacity]
|
|
307
|
+
out["compression_auto_train"] = true
|
|
308
|
+
out["compression_dict_capacity"] = auto_dict[:capacity] if auto_dict[:capacity]
|
|
309
|
+
else
|
|
310
|
+
raise TypeError, "auto_dict: must be true, false, or a Hash; got #{auto_dict.class}"
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
if opts.key?(:compression_threshold)
|
|
315
|
+
out["compression_threshold"] = opts[:compression_threshold]
|
|
316
|
+
end
|
|
317
|
+
out["max_recv_dict_size"] = opts[:max_recv_dict_size] if opts.key?(:max_recv_dict_size)
|
|
318
|
+
if opts.key?(:compression_offload_threshold)
|
|
319
|
+
out["compression_offload_threshold"] = opts[:compression_offload_threshold] || -1
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
out
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
def default_compression_option(key)
|
|
327
|
+
key == "compression_auto_train" ? false : nil
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
def validate_positive!(label, value)
|
|
332
|
+
return if value.respond_to?(:positive?) && value.positive?
|
|
333
|
+
|
|
334
|
+
raise ArgumentError, "#{label} must be positive"
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
def validate_zstd_level!(level)
|
|
339
|
+
return if level.is_a?(Integer) && (-8..4).cover?(level)
|
|
340
|
+
|
|
341
|
+
raise ArgumentError, "zstd compression level must be -8..4, got #{level.inspect}"
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
|
|
259
345
|
def extract_mechanism(h)
|
|
260
346
|
mech = @options.mechanism
|
|
261
347
|
case mech
|
data/lib/omq/rust/version.rb
CHANGED