@decentnetwork/peer 0.1.155 → 0.1.156

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 (2) hide show
  1. package/dist/peer.js +45 -1
  2. package/package.json +1 -1
package/dist/peer.js CHANGED
@@ -93,6 +93,12 @@ const SELF_ANNOUNCE_INTERVAL_MS = readEnvInt("DECENT_SELF_ANNOUNCE_INTERVAL_MS",
93
93
  // abandoned run is left to finish or hang on its own; what matters is that the
94
94
  // NEXT tick is allowed to start.
95
95
  const SELF_ANNOUNCE_WATCHDOG_MARGIN_MS = readEnvInt("DECENT_SELF_ANNOUNCE_WATCHDOG_MARGIN_MS", 15000);
96
+ // Longest a self-announce pause may hold before it releases itself. The only
97
+ // caller wraps a single friend-request send, which has its own 8s announce
98
+ // deadline plus route discovery; 60s is well clear of a slow-but-working send
99
+ // and well short of "the peer is now invisible".
100
+ const SELF_ANNOUNCE_PAUSE_MAX_MS = readEnvInt("DECENT_SELF_ANNOUNCE_PAUSE_MAX_MS", 60_000);
101
+ const FAULT_REQUEST_HANG = process.env.DECENT_FAULT_REQUEST_HANG === "1";
96
102
  // How long a stored announce entry stays useful to someone looking us up.
97
103
  // toxcore expires announce entries on roughly this timescale, so a node that
98
104
  // acknowledged a store longer ago than this can no longer be counted on.
@@ -1101,6 +1107,13 @@ export class Peer {
1101
1107
  }
1102
1108
  const resumeSelfAnnounce = this.#pauseSelfAnnounce();
1103
1109
  try {
1110
+ // Fault injection, off unless DECENT_FAULT_REQUEST_HANG=1. Hangs inside
1111
+ // the paused region — the shape that killed self-announce in the
1112
+ // browser — so the pause expiry can be tested rather than argued for.
1113
+ if (FAULT_REQUEST_HANG) {
1114
+ this.#debugLog("FAULT: hanging inside the self-announce pause forever");
1115
+ await new Promise(() => { });
1116
+ }
1104
1117
  if (this.#selfAnnouncePromise) {
1105
1118
  await this.#selfAnnouncePromise.catch(() => { });
1106
1119
  }
@@ -7347,11 +7360,42 @@ export class Peer {
7347
7360
  const recentBonus = Date.now() - h.lastOkMs < 60_000 ? 2 : 0;
7348
7361
  return (h.ok * 2) - h.fail + recentBonus;
7349
7362
  }
7363
+ /**
7364
+ * Pause the self-announce loop, with an expiry.
7365
+ *
7366
+ * The pause is released in a `finally`, which is correct right up until the
7367
+ * guarded body never finishes. sendFriendRequest awaits a relay send inside
7368
+ * that body, and in a browser a backgrounded tab can leave that socket
7369
+ * neither open nor errored — so the `finally` never runs, the depth stays at
7370
+ * 1, and self-announce is dead forever.
7371
+ *
7372
+ * This latch sits BEFORE the watchdog in #ensureSelfAnnounceLoop: the tick
7373
+ * returns on pause depth without ever calling #runSelfAnnounce, so bounding
7374
+ * the run was not enough on its own. Measured on app.beagle.chat after the
7375
+ * watchdog shipped: announce age still climbing past 700s while the page's
7376
+ * other timers ran normally.
7377
+ *
7378
+ * A pause is a short-lived thing — a few seconds around one send. One that
7379
+ * outlives this window is a bug somewhere upstream, and the loop matters
7380
+ * more than the pause does.
7381
+ */
7350
7382
  #pauseSelfAnnounce() {
7351
7383
  this.#selfAnnouncePauseDepth += 1;
7352
- return () => {
7384
+ let released = false;
7385
+ const release = (viaTimeout) => {
7386
+ if (released)
7387
+ return;
7388
+ released = true;
7389
+ clearTimeout(expiry);
7353
7390
  this.#selfAnnouncePauseDepth = Math.max(0, this.#selfAnnouncePauseDepth - 1);
7391
+ if (viaTimeout) {
7392
+ this.#debugLog(`self-announce pause expired after ${Math.round(SELF_ANNOUNCE_PAUSE_MAX_MS / 1000)}s — ` +
7393
+ `releasing it; whoever took it never gave it back`);
7394
+ }
7354
7395
  };
7396
+ const expiry = setTimeout(() => release(true), SELF_ANNOUNCE_PAUSE_MAX_MS);
7397
+ expiry.unref?.();
7398
+ return () => release(false);
7355
7399
  }
7356
7400
  async #runSelfAnnounce(force, deadlineMs) {
7357
7401
  if (this.#selfAnnouncePromise) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decentnetwork/peer",
3
- "version": "0.1.155",
3
+ "version": "0.1.156",
4
4
  "description": "Pure TypeScript port of Elastos Carrier (toxcore-derived) P2P messaging. DHT, onion routing, TCP relay, FlatBuffers app payloads, Express offline relay. Wire-compatible with iOS Beagle and the Carrier C SDK.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",