omq 0.28.7 → 0.28.9

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: 69989ec63abfcf84fc4a2c6fb6900601a426da84efceda4214756d6cfe6c5730
4
+ data.tar.gz: 8fd5f283d00aa4b41e9a43bf9fd0f9d818e8a33fdfb6e8fba300b815cb87581d
5
5
  SHA512:
6
- metadata.gz: 2e628c0814a1596514e7ec4f845689c90392c74d5d45652c1e6efa8c85acc801cb88a04d0a5acaa95a6696467d76ea609cac2b93e7de00347fb980104a81564a
7
- data.tar.gz: e69d5a0698a8f2a2879378dbd35b983e0e45ef52ea323c3a439947b5f657a734333cdec0c869389bf186dabc92beee3fba0093f5498cf67f6ab49ca7e243a868
6
+ metadata.gz: c6a18373a24aee32befeb94f684770f23784417af36f9d6d60475ee1969559105ff4403223dea44caeeafcfe3e18899a6f0e95493a4e05486336a15b37933194
7
+ data.tar.gz: 21e86d33a77985738681f0d248214ccf5b85c2dde32e8efcf94b673ac1323d6a8c434c6b9b04a6315374b4eb129924ab5801af341f79aceb983c33056904f789
data/CHANGELOG.md CHANGED
@@ -2,6 +2,30 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.28.9] - 2026-08-26
6
+
7
+ ### Fixed
8
+
9
+ - Used `SocketError` when `Socket::ResolutionError` is unavailable, so
10
+ `require "omq"` works on JRuby.
11
+
12
+ ## [0.28.8] - 2026-08-08
13
+
14
+ ### Added
15
+
16
+ - Imported `omq-cli` under `gems/omq-cli` and wired it into monorepo
17
+ test and release tasks.
18
+ - Added `OMQ_BACKEND` support to `omq-cli` for choosing `ruby`, `rust`,
19
+ or `libzmq` as the default socket backend.
20
+ - Made `omq -v` print the effective socket backend at startup.
21
+ - Added `Socket#closed?`.
22
+
23
+ ### Changed
24
+
25
+ - Removed TruffleRuby Async compatibility shims. The pure Ruby backend now
26
+ requires a native `Fiber.scheduler`.
27
+ - Made `Socket#monitor` require native scheduler support.
28
+
5
29
  ## [0.28.7] - 2026-08-02
6
30
 
7
31
  ### 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,15 @@ 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 and JRuby
65
+ should use the Rust backend with `backend: :rust`; the pure Ruby backend is
66
+ not supported there because OMQ needs native `Fiber.scheduler` behavior.
67
+ JRuby support uses OMQ.java on Java 25 or newer. The Java gem selects the
68
+ matching OMQ.java artifact on Linux x86_64, macOS aarch64, macOS x86_64, and
69
+ Windows x86_64.
70
+
62
71
  ## Quick Start
63
72
 
64
73
  ### Request / Reply
@@ -217,8 +226,12 @@ See the [omq-cli README](https://github.com/paddor/omq-cli) for full documentati
217
226
 
218
227
  ## Optional Rust backend
219
228
 
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.
229
+ Install `omq-backend-rust` for an OMQ.rs backend through the first-class
230
+ `omq-rs` binding. Same socket API, with connection handling on a Tokio runtime.
231
+
232
+ The Rust backend also supports TruffleRuby. The pure Ruby backend currently
233
+ requires MRI-style native `Fiber.scheduler` support, so use `backend: :rust`
234
+ on TruffleRuby.
222
235
 
223
236
  ```ruby
224
237
  require "omq/backend/rust"
data/lib/omq/constants.rb CHANGED
@@ -43,6 +43,7 @@ module OMQ
43
43
  IO::Stream::ConnectionResetError,
44
44
  ]
45
45
 
46
+ RESOLUTION_ERROR = defined?(Socket::ResolutionError) ? Socket::ResolutionError : SocketError
46
47
 
47
48
  # Errors raised when a peer cannot be reached.
48
49
  CONNECTION_FAILED = [
@@ -52,7 +53,7 @@ module OMQ
52
53
  Errno::EHOSTUNREACH,
53
54
  Errno::ENETUNREACH,
54
55
  Errno::EPROTOTYPE, # IPC: existing socket file is SOCK_DGRAM, not SOCK_STREAM
55
- Socket::ResolutionError,
56
+ RESOLUTION_ERROR,
56
57
  ]
57
58
 
58
59
 
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,9 @@ module OMQ
16
17
  #
17
18
  module Reactor
18
19
  THREAD_NAME = 'omq-io'
20
+ NATIVE_FIBER_SCHEDULER = RUBY_ENGINE != "jruby" &&
21
+ Fiber.respond_to?(:scheduler) &&
22
+ Fiber.method(:scheduler).source_location.nil?
19
23
 
20
24
  @mutex = Mutex.new
21
25
  @pid = nil
@@ -31,6 +35,11 @@ module OMQ
31
35
  attr_reader :lingers
32
36
 
33
37
 
38
+ def native_fiber_scheduler?
39
+ NATIVE_FIBER_SCHEDULER
40
+ end
41
+
42
+
34
43
  # Returns the root Async task inside the shared IO thread.
35
44
  # Starts the thread exactly once (double-checked lock).
36
45
  #
@@ -76,6 +85,12 @@ module OMQ
76
85
  else
77
86
  yield
78
87
  end
88
+ elsif !native_fiber_scheduler?
89
+ if timeout
90
+ Timeout.timeout(timeout, IO::TimeoutError) { yield }
91
+ else
92
+ yield
93
+ end
79
94
  else
80
95
  result = Async::Promise.new
81
96
  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.9"
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.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Patrik Wenger