Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,25 @@

> **Note:** Versions 0.3.24 – 0.3.54 were released as git tags without changelog entries. Changelog resumes at 0.3.55 below.

## 0.3.83

### Fixed

- **Stale-prior threshold lowered from 10s to 1s** in `SymNode.addPeer`
dedup. Mirrors `@sym-bot/sym` v0.5.5 on the Node side. The 10s window
shipped in v0.3.81 was too lenient: when a peer process was killed
and quickly relaunched, the old run had typically sent a CMB seconds
before death, so `lastSeen` was still within the 10s window. The
dedup logic then rejected the legitimate redial as a
same-direction-duplicate, producing `connection ready → immediate
disconnect` with no handshake-complete on the dialing side.

Lowered to 1s. Sub-second TCP-retry races during initial handshake
still keep prior (the case the same-direction-duplicate rule was
designed for); peer restarts with ≥1s between kill and re-dial now
recover within the application layer instead of being blocked until
OS keepalive reaps the socket (~100s).

## 0.3.82

### Fixed
Expand Down
9 changes: 8 additions & 1 deletion Sources/SYM/SymNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -987,7 +987,14 @@ public final class SymNode {
/// TCP keepalive (set in SymPeerSession.tcpParametersWithKeepalive)
/// reaps within ~4s, but until that fires the lastSeen-age check is
/// the application-level guard.
static let staleAfterSeconds: TimeInterval = 10
/// 1-second threshold (NOT heartbeat-interval=10s). When a peer
/// process is killed and quickly relaunches, its old run sent a CMB
/// seconds before death, so lastSeen is still recent. A 10s threshold
/// missed this and the dedup-reject path killed the legitimate redial.
/// 1s tolerates sub-second TCP-retry races during initial handshake
/// while letting normal peer-restart (≥1s gap between kill and re-dial)
/// recover within the application layer.
static let staleAfterSeconds: TimeInterval = 1

private func addPeer(_ session: SymPeerSession, nodeId: String, peerName: String, isOutbound: Bool) {
let outcome: AddPeerOutcome = peerQueue.sync {
Expand Down