omq 0.28.7 → 0.28.8

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: 7ba6c1a230231646b3a6c62e2989df1b7e1cc8a0f221ecaa36866d34fa1d0e37
4
- data.tar.gz: c8fd13bec0c8bc71ce65d7986fc90e2d4269a00c9aceecde3f15f5594ec83550
3
+ metadata.gz: 6ed8a560eb7abf29a97bdae6a35baaf18bfe1ef47476a33691f7d5ad2fdf2914
4
+ data.tar.gz: 91b6416e4ce9110cf13f73bd7a7b8fdc97b994132f718f99f3dcd2cff4030857
5
5
  SHA512:
6
- metadata.gz: 2e628c0814a1596514e7ec4f845689c90392c74d5d45652c1e6efa8c85acc801cb88a04d0a5acaa95a6696467d76ea609cac2b93e7de00347fb980104a81564a
7
- data.tar.gz: e69d5a0698a8f2a2879378dbd35b983e0e45ef52ea323c3a439947b5f657a734333cdec0c869389bf186dabc92beee3fba0093f5498cf67f6ab49ca7e243a868
6
+ metadata.gz: 41fbe26e73c2dae30b30a74ba347e9c1a52781ec13d7ecc4ee98f80e715e8a3c83f95a47adeac5294238a1cc29b8359bc1c7b6ae96320036855f789062b87eb7
7
+ data.tar.gz: 539696d1162ac357f319664657a33cb3cada7d6968a42b1cf3855498fee1ec1deaa1ff6ab340860c536784cfde2d53328496f7014c398b933ab36843ff86a02a
data/CHANGELOG.md CHANGED
@@ -2,6 +2,23 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.28.8] - 2026-08-08
6
+
7
+ ### Added
8
+
9
+ - Imported `omq-cli` under `gems/omq-cli` and wired it into monorepo
10
+ test and release tasks.
11
+ - Added `OMQ_BACKEND` support to `omq-cli` for choosing `ruby`, `rust`,
12
+ or `libzmq` as the default socket backend.
13
+ - Made `omq -v` print the effective socket backend at startup.
14
+ - Added `Socket#closed?`.
15
+
16
+ ### Changed
17
+
18
+ - Removed TruffleRuby Async compatibility shims. The pure Ruby backend now
19
+ requires a native `Fiber.scheduler`.
20
+ - Made `Socket#monitor` require native scheduler support.
21
+
5
22
  ## [0.28.7] - 2026-08-02
6
23
 
7
24
  ### Fixed
data/README.md CHANGED
@@ -11,8 +11,8 @@
11
11
  >
12
12
  > Ruby 4.0 + YJIT on a Linux VM. See [`bench/`](bench/) for full results
13
13
 
14
- `gem install omq` and you're done. No libzmq, no compiler, no system packages,
15
- just Ruby talking to every other ZeroMQ peer out there.
14
+ `gem install omq` and you're done on MRI Ruby. No libzmq, no compiler, no
15
+ system packages, just Ruby talking to every other ZeroMQ peer out there.
16
16
 
17
17
  ØMQ gives your Ruby processes a way to talk to each other, and to anything
18
18
  else speaking ZeroMQ, without a broker in the middle. Same API whether they
@@ -26,7 +26,7 @@ walkthrough of every major pattern with working code.
26
26
  ## Highlights
27
27
 
28
28
  - **Zero dependencies on C**: no extensions, no FFI, no libzmq. `gem install`
29
- just works everywhere
29
+ just works on supported MRI Rubies
30
30
  - **Fast**: YJIT-optimized hot paths, batched sends, GC-tuned allocations,
31
31
  buffered I/O via [io-stream](https://github.com/socketry/io-stream),
32
32
  direct-pipe inproc bypass
@@ -59,6 +59,12 @@ gem install omq
59
59
  gem 'omq'
60
60
  ```
61
61
 
62
+ ### Ruby Engines
63
+
64
+ MRI Ruby 3.3 and 4.0 can use the pure Ruby backend. TruffleRuby should use
65
+ the Rust backend with `backend: :rust`; the pure Ruby backend is not supported
66
+ there because OMQ needs native `Fiber.scheduler` behavior.
67
+
62
68
  ## Quick Start
63
69
 
64
70
  ### Request / Reply
@@ -220,6 +226,10 @@ See the [omq-cli README](https://github.com/paddor/omq-cli) for full documentati
220
226
  Install `omq-backend-rust` for a Rust/omq-tokio backend. Same socket API,
221
227
  but connection handling runs in native code on a Tokio runtime.
222
228
 
229
+ The Rust backend also supports TruffleRuby. The pure Ruby backend currently
230
+ requires MRI-style native `Fiber.scheduler` support, so use `backend: :rust`
231
+ on TruffleRuby.
232
+
223
233
  ```ruby
224
234
  require "omq/backend/rust"
225
235
  push = OMQ::PUSH.new(backend: :rust)
data/lib/omq/reactor.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "async"
4
+ require "timeout"
4
5
 
5
6
  module OMQ
6
7
  # Shared IO reactor for the Ruby backend.
@@ -16,6 +17,7 @@ module OMQ
16
17
  #
17
18
  module Reactor
18
19
  THREAD_NAME = 'omq-io'
20
+ NATIVE_FIBER_SCHEDULER = Fiber.respond_to?(:scheduler) && Fiber.method(:scheduler).source_location.nil?
19
21
 
20
22
  @mutex = Mutex.new
21
23
  @pid = nil
@@ -31,6 +33,11 @@ module OMQ
31
33
  attr_reader :lingers
32
34
 
33
35
 
36
+ def native_fiber_scheduler?
37
+ NATIVE_FIBER_SCHEDULER
38
+ end
39
+
40
+
34
41
  # Returns the root Async task inside the shared IO thread.
35
42
  # Starts the thread exactly once (double-checked lock).
36
43
  #
@@ -76,6 +83,12 @@ module OMQ
76
83
  else
77
84
  yield
78
85
  end
86
+ elsif !native_fiber_scheduler?
87
+ if timeout
88
+ Timeout.timeout(timeout, IO::TimeoutError) { yield }
89
+ else
90
+ yield
91
+ end
79
92
  else
80
93
  result = Async::Promise.new
81
94
  root_task # ensure started
data/lib/omq/readable.rb CHANGED
@@ -17,7 +17,11 @@ module OMQ
17
17
  if @engine.on_io_thread?
18
18
  Reactor.run(timeout: @options.read_timeout) { @engine.dequeue_recv }
19
19
  elsif (timeout = @options.read_timeout)
20
- Async::Task.current.with_timeout(timeout, IO::TimeoutError) { @engine.dequeue_recv }
20
+ if Reactor.native_fiber_scheduler?
21
+ Async::Task.current.with_timeout(timeout, IO::TimeoutError) { @engine.dequeue_recv }
22
+ else
23
+ Reactor.run(timeout:) { @engine.dequeue_recv }
24
+ end
21
25
  else
22
26
  @engine.dequeue_recv
23
27
  end
data/lib/omq/socket.rb CHANGED
@@ -202,6 +202,10 @@ module OMQ
202
202
  # task.stop
203
203
  #
204
204
  def monitor(verbose: false, &block)
205
+ unless Reactor.native_fiber_scheduler?
206
+ raise NotImplementedError, "Socket#monitor requires native Fiber.scheduler"
207
+ end
208
+
205
209
  ensure_parent_task
206
210
 
207
211
  queue = Async::LimitedQueue.new(64)
@@ -245,6 +249,12 @@ module OMQ
245
249
  end
246
250
 
247
251
 
252
+ # @return [Boolean] true once the underlying engine is closed.
253
+ def closed?
254
+ @engine.closed?
255
+ end
256
+
257
+
248
258
  # Immediate hard stop. Skips the linger drain and cascades teardown
249
259
  # through the socket-level Async::Barrier. Intended for crash-path
250
260
  # cleanup or when the caller already knows no pending sends matter.
@@ -316,6 +326,10 @@ module OMQ
316
326
  @options.conflate = conflate
317
327
  @options.on_mute = on_mute if on_mute
318
328
  backend_name = (backend || :ruby).to_sym
329
+ if backend_name == :ruby && !Reactor.native_fiber_scheduler?
330
+ raise NotImplementedError, "Ruby backend requires native Fiber.scheduler; use backend: :rust"
331
+ end
332
+
319
333
  require_backend(backend_name) unless Backend.registered?(backend_name)
320
334
 
321
335
  engine_class = Backend.fetch(backend_name)
data/lib/omq/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OMQ
4
- VERSION = "0.28.7"
4
+ VERSION = "0.28.8"
5
5
  end
data/lib/omq/writable.rb CHANGED
@@ -46,7 +46,11 @@ module OMQ
46
46
  if @engine.on_io_thread?
47
47
  Reactor.run(timeout: @options.write_timeout) { @engine.enqueue_send(parts) }
48
48
  elsif (timeout = @options.write_timeout)
49
- Async::Task.current.with_timeout(timeout, IO::TimeoutError) { @engine.enqueue_send(parts) }
49
+ if Reactor.native_fiber_scheduler?
50
+ Async::Task.current.with_timeout(timeout, IO::TimeoutError) { @engine.enqueue_send(parts) }
51
+ else
52
+ Reactor.run(timeout:) { @engine.enqueue_send(parts) }
53
+ end
50
54
  else
51
55
  @engine.enqueue_send(parts)
52
56
  end
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.28.7
4
+ version: 0.28.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Patrik Wenger