@fairfox/polly 0.74.0 → 0.74.1

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.
@@ -606,13 +606,54 @@ export declare class MeshWebRTCAdapter extends NetworkAdapter {
606
606
  * theirs), open an initiating slot and fire the SDP offer. Otherwise
607
607
  * do nothing — either we are not interested in this peer, we are
608
608
  * already connected, or the other side is the one expected to
609
- * initiate. */
609
+ * initiate.
610
+ *
611
+ * A `peer-joined` for a peerId we already hold a slot for is first
612
+ * routed through {@link evictStaleSlotForRejoin}: the notification is
613
+ * authoritative proof the remote peer's signalling presence is fresh,
614
+ * so a slot left over from an earlier incarnation of the same peerId
615
+ * is torn down rather than left to wedge rediscovery. Polly issue
616
+ * #133. */
610
617
  handlePeerJoined(remotePeerId: string): void;
611
618
  /** Handle the signalling server's `peers-present` notification sent
612
619
  * once to a newcomer. Applies the same filter as handlePeerJoined to
613
620
  * every listed peer, so a device joining into an established lobby
614
- * dials every knownPeer it is meant to initiate to in one pass. */
621
+ * dials every knownPeer it is meant to initiate to in one pass.
622
+ *
623
+ * Like {@link handlePeerJoined}, each listed peer is first run
624
+ * through {@link evictStaleSlotForRejoin} so a `peers-present` frame
625
+ * received on a signalling *reconnect* clears any stale slot before
626
+ * the dial path re-evaluates it. Polly issue #133. */
615
627
  handlePeersPresent(peerIds: string[]): void;
628
+ /** Tear down a slot left over from an earlier incarnation of a peer
629
+ * that has just (re)appeared in the signalling roster, so the dial
630
+ * path can rebuild it.
631
+ *
632
+ * A `peer-joined` / `peers-present` frame is authoritative proof that
633
+ * the remote peer's signalling presence is fresh: its
634
+ * {@link MeshSignalingClient} has just sent a `join`. If we are still
635
+ * holding a slot for that peerId, the slot belongs to a previous
636
+ * incarnation — *unless* the peer kept a live WebRTC session across
637
+ * its own signalling reconnect, in which case the data channel is
638
+ * still `open` on a `connected` connection and the slot is genuinely
639
+ * sound (peers talk directly once the channel is up; signalling is
640
+ * intermittent). That one shape is kept; every other shape is stale.
641
+ *
642
+ * Polly issue #133: before this, a stale slot wedged rediscovery of a
643
+ * peer that reuses its peerId across short-lived sessions (a CLI
644
+ * `chat send` re-run from the same keyring is the canonical case).
645
+ * The `slot-already-exists` gate in {@link evaluateInitiation}
646
+ * blocked the survivor from re-dialling, and {@link handleOffer}'s
647
+ * glare rule made the lexicographically-higher survivor ignore the
648
+ * newcomer's offer too — so the pair never reconnected until the
649
+ * {@link slotIdleTimeoutMs} watchdog reaped the corpse, far too late
650
+ * for the request that triggered the rejoin.
651
+ *
652
+ * A handshake that is still young and negotiating (`new`/`connecting`
653
+ * within {@link slotNeverConnectedTimeoutMs}) is left alone — a
654
+ * duplicate frame arriving mid-handshake must not nuke a connection
655
+ * that simply is not done yet. */
656
+ private evictStaleSlotForRejoin;
616
657
  /** Construct an initiating slot inside a per-peer try/catch and
617
658
  * record any throw as a `fatal-error` rejection on the per-peer
618
659
  * decision map so the snapshot surface names it. Every dial entry
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fairfox/polly",
3
- "version": "0.74.0",
3
+ "version": "0.74.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Multi-execution-context framework with reactive state and cross-context messaging for Chrome extensions, PWAs, and worker-based applications",