omq 0.9.0 → 0.10.0

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.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +67 -0
  3. data/lib/omq/channel.rb +3 -3
  4. data/lib/omq/client_server.rb +6 -6
  5. data/lib/omq/engine.rb +641 -0
  6. data/lib/omq/options.rb +46 -0
  7. data/lib/omq/pair.rb +2 -2
  8. data/lib/omq/peer.rb +3 -3
  9. data/lib/omq/pub_sub.rb +6 -6
  10. data/lib/omq/push_pull.rb +2 -2
  11. data/lib/omq/radio_dish.rb +2 -2
  12. data/lib/omq/reactor.rb +128 -0
  13. data/lib/omq/readable.rb +42 -0
  14. data/lib/omq/req_rep.rb +4 -4
  15. data/lib/omq/router_dealer.rb +4 -4
  16. data/lib/omq/routing/channel.rb +83 -0
  17. data/lib/omq/routing/client.rb +56 -0
  18. data/lib/omq/routing/dealer.rb +57 -0
  19. data/lib/omq/routing/dish.rb +78 -0
  20. data/lib/omq/routing/fan_out.rb +131 -0
  21. data/lib/omq/routing/gather.rb +46 -0
  22. data/lib/omq/routing/pair.rb +86 -0
  23. data/lib/omq/routing/peer.rb +101 -0
  24. data/lib/omq/routing/pub.rb +60 -0
  25. data/lib/omq/routing/pull.rb +46 -0
  26. data/lib/omq/routing/push.rb +81 -0
  27. data/lib/omq/routing/radio.rb +140 -0
  28. data/lib/omq/routing/rep.rb +101 -0
  29. data/lib/omq/routing/req.rb +65 -0
  30. data/lib/omq/routing/round_robin.rb +168 -0
  31. data/lib/omq/routing/router.rb +110 -0
  32. data/lib/omq/routing/scatter.rb +82 -0
  33. data/lib/omq/routing/server.rb +101 -0
  34. data/lib/omq/routing/sub.rb +78 -0
  35. data/lib/omq/routing/xpub.rb +72 -0
  36. data/lib/omq/routing/xsub.rb +83 -0
  37. data/lib/omq/routing.rb +66 -0
  38. data/lib/omq/scatter_gather.rb +4 -4
  39. data/lib/omq/single_frame.rb +18 -0
  40. data/lib/omq/socket.rb +24 -9
  41. data/lib/omq/transport/inproc.rb +355 -0
  42. data/lib/omq/transport/ipc.rb +117 -0
  43. data/lib/omq/transport/tcp.rb +111 -0
  44. data/lib/omq/version.rb +1 -1
  45. data/lib/omq/writable.rb +65 -0
  46. data/lib/omq.rb +60 -4
  47. metadata +32 -33
  48. data/lib/omq/zmtp/engine.rb +0 -551
  49. data/lib/omq/zmtp/options.rb +0 -48
  50. data/lib/omq/zmtp/reactor.rb +0 -131
  51. data/lib/omq/zmtp/readable.rb +0 -29
  52. data/lib/omq/zmtp/routing/channel.rb +0 -81
  53. data/lib/omq/zmtp/routing/client.rb +0 -56
  54. data/lib/omq/zmtp/routing/dealer.rb +0 -57
  55. data/lib/omq/zmtp/routing/dish.rb +0 -80
  56. data/lib/omq/zmtp/routing/fan_out.rb +0 -131
  57. data/lib/omq/zmtp/routing/gather.rb +0 -48
  58. data/lib/omq/zmtp/routing/pair.rb +0 -84
  59. data/lib/omq/zmtp/routing/peer.rb +0 -100
  60. data/lib/omq/zmtp/routing/pub.rb +0 -62
  61. data/lib/omq/zmtp/routing/pull.rb +0 -48
  62. data/lib/omq/zmtp/routing/push.rb +0 -80
  63. data/lib/omq/zmtp/routing/radio.rb +0 -139
  64. data/lib/omq/zmtp/routing/rep.rb +0 -101
  65. data/lib/omq/zmtp/routing/req.rb +0 -65
  66. data/lib/omq/zmtp/routing/round_robin.rb +0 -143
  67. data/lib/omq/zmtp/routing/router.rb +0 -109
  68. data/lib/omq/zmtp/routing/scatter.rb +0 -81
  69. data/lib/omq/zmtp/routing/server.rb +0 -100
  70. data/lib/omq/zmtp/routing/sub.rb +0 -80
  71. data/lib/omq/zmtp/routing/xpub.rb +0 -74
  72. data/lib/omq/zmtp/routing/xsub.rb +0 -86
  73. data/lib/omq/zmtp/routing.rb +0 -65
  74. data/lib/omq/zmtp/single_frame.rb +0 -20
  75. data/lib/omq/zmtp/transport/inproc.rb +0 -359
  76. data/lib/omq/zmtp/transport/ipc.rb +0 -118
  77. data/lib/omq/zmtp/transport/tcp.rb +0 -117
  78. data/lib/omq/zmtp/writable.rb +0 -61
  79. data/lib/omq/zmtp.rb +0 -81
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a14af693117ccfb193f54e9bc2a4faae9c2bf6396e7769abee97f279fd62fdba
4
- data.tar.gz: 1f5e99ae3b61402d2b9e506c84fdb07d2003695515d3f736159cf2c373cc39d0
3
+ metadata.gz: 3a81ea3e22e2133f508016129454fca72393068b259400e3d47aaf92d0948136
4
+ data.tar.gz: 71839df55e8ae9edb9db9710b77c5449853cde909c60867958a46e8350f27ead
5
5
  SHA512:
6
- metadata.gz: 76539e2a9fbdcbe59590e1fa499e300b8f7ad3d527255af6f94665139c3c0a60151f0b82202df372df1cdbc16e90f46369aa7b159342f951cf52babc897b837c
7
- data.tar.gz: dba241d3283a0a0330ba0d12081c08f3ae074acaa8be7b1e9292dee9c19a483d822f896a4442ec585005dbeb36efa704b87f51c53e07c1de0ede54a85150f55c
6
+ metadata.gz: 9e9d603fb6f44b53626e37d88da5dea1297f932bfbc7b3af0b32e5ab4ebdc6c2151f4b7482bca70d5060d31ffc49ba3c771603b6ed1b4dd17ed51733339de67d
7
+ data.tar.gz: b40525791795b8e040a4a275a628c1cdca42eab43fcabfab76407de97f669ff9c1b21d05490509c0e0f5cd0b53505c7f85281343b2c312bdb89fd3eee7d4af75
data/CHANGELOG.md CHANGED
@@ -1,5 +1,72 @@
1
1
  # Changelog
2
2
 
3
+ ## Unreleased
4
+
5
+ ## 0.10.0 — 2026-04-01
6
+
7
+ ### Added
8
+
9
+ - **Auto-close sockets via Async task tree** — all engine tasks (accept
10
+ loops, connection tasks, send/recv pumps, heartbeats, reconnect loops,
11
+ reapers) now live under the caller's Async task. When the `Async` block
12
+ exits, tasks are stopped and `ensure` blocks close IO resources.
13
+ Explicit `Socket#close` is no longer required (but remains available
14
+ and idempotent).
15
+ - **Non-Async usage** — sockets work outside `Async do…end`. A shared IO
16
+ thread hosts the task tree; all blocking operations (bind, connect,
17
+ send, receive, close) are dispatched to it transparently via
18
+ `Reactor.run`. The IO thread shuts down cleanly at process exit,
19
+ respecting the longest linger across all sockets.
20
+ - **Recv prefetching** — `#receive` internally drains up to 64 messages
21
+ per queue dequeue, buffering the excess behind a Mutex. Subsequent
22
+ calls return from the buffer without touching the queue. Thread-safe
23
+ on JRuby. TCP 64B pipelined: 30k → 221k msg/s (7x).
24
+
25
+ ### Changed
26
+
27
+ - **Transports are pure IO** — TCP and IPC transports no longer spawn
28
+ tasks. They create server sockets and return them; Engine owns the
29
+ accept loops.
30
+ - **Reactor simplified** — `spawn_pump` and `PumpHandle` removed.
31
+ Reactor exposes `root_task` (shared IO thread's root Async task)
32
+ and `run` (cross-thread dispatch). `stop!` respects max linger.
33
+ - **Flatten `OMQ::ZMTP` namespace into `OMQ`** — with the ZMTP protocol
34
+ layer extracted to `protocol-zmtp`, the `ZMTP` sub-namespace no longer
35
+ makes sense. Engine, routing, transport, and mixins now live directly
36
+ under `OMQ::`. Protocol-zmtp types are referenced as `Protocol::ZMTP::*`.
37
+
38
+ ### Performance
39
+
40
+ - **Direct pipe bypass for single-peer inproc** — PAIR, CHANNEL, and
41
+ single-peer RoundRobin types (PUSH, REQ, DEALER, CLIENT, SCATTER)
42
+ enqueue directly into the receiver's recv queue, skipping the
43
+ send_queue and send pump entirely.
44
+ Inproc PUSH/PULL: 200k → 980k msg/s (5x).
45
+ - **Uncapped send queue drain** — the send pump drains the entire queue
46
+ per cycle instead of capping at 64 messages. IO::Stream auto-flushes
47
+ at 64 KB, so writes hit the wire naturally under load.
48
+ IPC latency −12%, TCP latency −10%.
49
+ - **Remove `.b` allocations from PUB/SUB subscription matching** —
50
+ `FanOut#subscribed?` no longer creates temporary binary strings per
51
+ comparison; both topic and prefix are guaranteed binary at rest.
52
+ - **Reuse `written` Set and `latest` Hash across batches** in all send
53
+ pumps (fan-out, round-robin, router, server, peer, rep, radio),
54
+ eliminating per-batch object allocation.
55
+ - **O(1) `connection_removed` for identity-routed sockets** — Router,
56
+ Server, and Peer now maintain a reverse index instead of scanning.
57
+ - **`freeze_message` fast path** — skip `.b.freeze` when the string is
58
+ already a frozen binary string.
59
+ - **Pre-frozen empty frame constants** for REQ/REP delimiter frames.
60
+
61
+ ### Fixed
62
+
63
+ - **Reapers no longer crash on inproc DirectPipe** — PUSH and SCATTER
64
+ reapers skipped for DirectPipe connections that have no receive queue
65
+ (latent bug previously masked by transient task error swallowing).
66
+ - **`send_pump_idle?` made public** on all routing strategies — was
67
+ accidentally private, crashing `Engine#drain_send_queues` with
68
+ linger > 0.
69
+
3
70
  ## 0.9.0 — 2026-03-31
4
71
 
5
72
  ### Breaking
data/lib/omq/channel.rb CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  module OMQ
4
4
  class CHANNEL < Socket
5
- include ZMTP::Readable
6
- include ZMTP::Writable
7
- include ZMTP::SingleFrame
5
+ include Readable
6
+ include Writable
7
+ include SingleFrame
8
8
 
9
9
  def initialize(endpoints = nil, linger: 0)
10
10
  _init_engine(:CHANNEL, linger: linger)
@@ -2,9 +2,9 @@
2
2
 
3
3
  module OMQ
4
4
  class CLIENT < Socket
5
- include ZMTP::Readable
6
- include ZMTP::Writable
7
- include ZMTP::SingleFrame
5
+ include Readable
6
+ include Writable
7
+ include SingleFrame
8
8
 
9
9
  def initialize(endpoints = nil, linger: 0)
10
10
  _init_engine(:CLIENT, linger: linger)
@@ -13,9 +13,9 @@ module OMQ
13
13
  end
14
14
 
15
15
  class SERVER < Socket
16
- include ZMTP::Readable
17
- include ZMTP::Writable
18
- include ZMTP::SingleFrame
16
+ include Readable
17
+ include Writable
18
+ include SingleFrame
19
19
 
20
20
  def initialize(endpoints = nil, linger: 0)
21
21
  _init_engine(:SERVER, linger: linger)