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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c552d7ca25d216c752732579deddf1cf357a8bd1b71cfec2be322f5e1d1645ef
4
- data.tar.gz: 76e666f63269f5d69384aa04a6298144b78171c4f69d397a98ebfcb5ff1ccf9e
3
+ metadata.gz: a08620eb9fd1a781752e72f44186bbaee5fcefd37d92560901aa8fb7c6e4f269
4
+ data.tar.gz: 891cc692da98d5cd7e2daf2a461e06b4c7b41de91f88964d1d9f7cbc20616f9a
5
5
  SHA512:
6
- metadata.gz: 4a2974b9286be09db0671bf8784346e88bc58cbcdf00a3a22d58309a8a852e33164d044565315fcde4f869a11e3f294d38ed313f45196967259a1d2e46bfad81
7
- data.tar.gz: e406b0651722cff4b807096ec15b5d8cb9cfd8e5e314285250af47ecaf119b79af3e0aa46265cab53e1b4d6b7ca6eea38f7b03cd31205ed0575d186dd43f9bff
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.24.1", default-features = false }
21
- omq-tokio = { version = "=0.20.2", default-features = false }
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.8", features = ["async"] }
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,
@@ -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
@@ -2,6 +2,6 @@
2
2
 
3
3
  module OMQ
4
4
  module Rust
5
- VERSION = "0.1.5"
5
+ VERSION = "0.1.6"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omq-backend-rust
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Patrik Wenger