omq 0.17.0 → 0.17.2
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 +30 -0
- data/lib/omq/engine/connection_lifecycle.rb +5 -1
- data/lib/omq/engine/reconnect.rb +20 -1
- data/lib/omq/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: f8a35ab8a212a111e78889494ac1eb18f780b6315eb3993eb83d04ae7ebdb222
|
|
4
|
+
data.tar.gz: 32727fe82814e3d36843dcbd82d66ecfbd9c26e5c36e7a173bdcf164dd649f75
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1f78b8ff8a907b606ec376a7186a09b77b91317c91f3bdb1ff7ebd600d36d6e6fea4738b72dc4ddd3c611225df4a9c27fbd8418fe73dfcdf7a20985fdee5516b
|
|
7
|
+
data.tar.gz: 3811837748c18669dd6dc604c8253cfdb7b0e26a6c9eda3b61a4c711ac441f88b58c283701e6985880aa03d963338b53cc4271c3e456e6499498f9ce21037d85
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.17.2 — 2026-04-10
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **Reconnect after handshake failure.** When a peer RST'd a TCP
|
|
8
|
+
connection mid-ZMTP-handshake (e.g. `LINGER 0` close against an
|
|
9
|
+
in-flight connect), `ConnectionLifecycle#handshake!` called
|
|
10
|
+
`transition!(:closed)` directly, bypassing `tear_down!` and its
|
|
11
|
+
`maybe_reconnect` call. `spawn_connection`'s `ensure close!` then
|
|
12
|
+
saw the state already `:closed` and did nothing — the endpoint died
|
|
13
|
+
silently with no reconnect ever scheduled. Now the handshake rescue
|
|
14
|
+
goes through `tear_down!(reconnect: true)`, emitting `:disconnected`
|
|
15
|
+
and scheduling reconnect like any other connection loss.
|
|
16
|
+
|
|
17
|
+
## 0.17.1 — 2026-04-10
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- **Reconnect sleeps are wall-clock quantized.** `Engine::Reconnect`
|
|
22
|
+
now sleeps until the next `delay`-sized grid tick instead of `delay`
|
|
23
|
+
from now (same math as `Async::Loop.quantized`). Multiple clients
|
|
24
|
+
reconnecting with the same interval wake up at the same instant,
|
|
25
|
+
collapsing staggered retries into aligned waves — easier to reason
|
|
26
|
+
about for observability and cache-warmup, and a server coming back
|
|
27
|
+
up sees one batch of accepts instead of a smear. Wall-clock (not
|
|
28
|
+
monotonic) on purpose: the grid has to line up across processes.
|
|
29
|
+
Anti-jitter by design. Exponential backoff still works: each
|
|
30
|
+
iteration quantizes to its own (growing) interval's grid, and
|
|
31
|
+
clients at the same backoff stage still align with each other.
|
|
32
|
+
|
|
3
33
|
## 0.17.0 — 2026-04-10
|
|
4
34
|
|
|
5
35
|
### Changed
|
|
@@ -89,7 +89,11 @@ module OMQ
|
|
|
89
89
|
rescue Protocol::ZMTP::Error, *CONNECTION_LOST => error
|
|
90
90
|
@engine.emit_monitor_event(:handshake_failed, endpoint: @endpoint, detail: { error: error })
|
|
91
91
|
conn&.close
|
|
92
|
-
|
|
92
|
+
# Full tear-down with reconnect: without this, spawn_connection's
|
|
93
|
+
# ensure-block close! sees :closed and skips maybe_reconnect,
|
|
94
|
+
# leaving the endpoint dead. Race is exposed when a peer RSTs
|
|
95
|
+
# mid-handshake (e.g. LINGER 0 close against an in-flight connect).
|
|
96
|
+
tear_down!(reconnect: true)
|
|
93
97
|
raise
|
|
94
98
|
end
|
|
95
99
|
|
data/lib/omq/engine/reconnect.rb
CHANGED
|
@@ -42,7 +42,7 @@ module OMQ
|
|
|
42
42
|
@engine.tasks << parent_task.async(transient: true, annotation: "reconnect #{@endpoint}") do
|
|
43
43
|
loop do
|
|
44
44
|
break if @engine.closed?
|
|
45
|
-
sleep delay if delay > 0
|
|
45
|
+
sleep quantized_wait(delay) if delay > 0
|
|
46
46
|
break if @engine.closed?
|
|
47
47
|
begin
|
|
48
48
|
@engine.transport_for(@endpoint).connect(@endpoint, @engine)
|
|
@@ -60,6 +60,25 @@ module OMQ
|
|
|
60
60
|
|
|
61
61
|
private
|
|
62
62
|
|
|
63
|
+
# Wall-clock quantized sleep: wait until the next +delay+-sized
|
|
64
|
+
# grid tick. Multiple clients reconnecting with the same interval
|
|
65
|
+
# wake up at the same instant, collapsing staggered retries into
|
|
66
|
+
# aligned waves. Same math as +Async::Loop.quantized+.
|
|
67
|
+
#
|
|
68
|
+
# Wall-clock (not monotonic) on purpose: the grid has to line up
|
|
69
|
+
# across processes, and monotonic clocks don't share an origin.
|
|
70
|
+
# Anti-jitter by design — if you want spread, don't call this.
|
|
71
|
+
#
|
|
72
|
+
# @param delay [Numeric] grid interval in seconds
|
|
73
|
+
# @param now [Float] wall-clock time in seconds (injectable for tests)
|
|
74
|
+
# @return [Float] seconds to sleep, always in (0, delay]
|
|
75
|
+
#
|
|
76
|
+
def quantized_wait(delay, now = Time.now.to_f)
|
|
77
|
+
wait = delay - (now % delay)
|
|
78
|
+
wait.positive? ? wait : delay
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
|
|
63
82
|
def init_delay(delay)
|
|
64
83
|
ri = @options.reconnect_interval
|
|
65
84
|
if ri.is_a?(Range)
|
data/lib/omq/version.rb
CHANGED