wireweave 0.3.46 → 0.3.47

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/package.json +1 -1
  2. package/src/relay-pool.js +23 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wireweave",
3
- "version": "0.3.46",
3
+ "version": "0.3.47",
4
4
  "description": "nostr + webrtc voice + data SDK. networking layer for 247420 projects.",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
package/src/relay-pool.js CHANGED
@@ -64,7 +64,15 @@ class RelayHealth {
64
64
  this.rank = 50;
65
65
  }
66
66
 
67
- recordConnectAttempt() { this.attempts++; }
67
+ // Recomputes rank on every attempt, not just on a successful signal —
68
+ // otherwise a relay that NEVER once connects (rank frozen at the ctor's
69
+ // neutral 50 forever, since recordConnectLatency/recordSustainedConnection/
70
+ // recordEoseLatency — the only other rank-recomputing call sites — never
71
+ // fire for it) reads as perpetually "average" no matter how many failed
72
+ // attempts pile up, defeating both healthReport() ranking and
73
+ // _maybeRotate's rank-gap rotation trigger for the exact "never connects
74
+ // at all" relay auto-rotation exists to route around.
75
+ recordConnectAttempt() { this.attempts++; this.rank = computeRank(this); }
68
76
 
69
77
  recordConnectLatency(ms) {
70
78
  this.connectLatencyMs = ewma(this.connectLatencyMs, ms);
@@ -250,7 +258,13 @@ export class RelayPool extends EventTarget {
250
258
  // Swap the worst currently-active relay for the best-ranked unused
251
259
  // candidate (fallback pool, or a previously-tried relay we disconnected
252
260
  // from) when the gap is large enough to be worth the churn of a new
253
- // connection. Never rotates below MIN_ACTIVE_RELAYS active URLs.
261
+ // connection. Never rotates below MIN_ACTIVE_RELAYS active URLs. Called
262
+ // from every ws.onclose (both the sustained-then-dropped branch AND the
263
+ // never-connected/failed-fast branch) — a relay that never manages to
264
+ // connect at all still needs evaluating here, since that IS the
265
+ // "consistently unhealthy" case rotation exists to route around, and its
266
+ // rank already reflects the failures via recordConnectAttempt's own
267
+ // computeRank call once attempts >= 2 (the sample floor enforced below).
254
268
  _maybeRotate() {
255
269
  if (!this.autoRotate || this._closed) return;
256
270
  const MIN_ACTIVE_RELAYS = 2;
@@ -378,11 +392,17 @@ export class RelayPool extends EventTarget {
378
392
  relay.reconnectDelay = 1000;
379
393
  health.recordSustainedConnection();
380
394
  this._scheduleSaveHealth();
381
- this._maybeRotate();
382
395
  } else {
383
396
  relay.failCount++;
384
397
  relay.reconnectDelay = Math.min(relay.reconnectDelay * 2, 30000);
385
398
  }
399
+ // Evaluate rotation on EVERY close, not just a sustained-then-dropped
400
+ // connection — a relay that never manages to connect at all (the
401
+ // `else` branch above) is exactly the "consistently unhealthy"
402
+ // relay auto-rotation exists to route around, and its rank already
403
+ // reflects that via computeRank's uptime/latency components once
404
+ // `attempts >= 2` (the sample floor _maybeRotate itself enforces).
405
+ this._maybeRotate();
386
406
  relay._openedAt = null;
387
407
  if (this._closed) return;
388
408
  const t = setTimeout(() => this._open(url), jitter(relay.reconnectDelay));