codehost 0.23.0 → 0.23.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.
- package/CHANGELOG.md +7 -0
- package/package.json +1 -1
- package/worker/room.ts +41 -15
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## [0.23.1](https://github.com/snomiao/codehost/compare/v0.23.0...v0.23.1) (2026-06-16)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Performance Improvements
|
|
5
|
+
|
|
6
|
+
* **signal:** exponential, unbounded backoff on the room sweep alarm ([fde1c43](https://github.com/snomiao/codehost/commit/fde1c43aa0dbc9274abb645ae43fc7cbd6712ee0))
|
|
7
|
+
|
|
1
8
|
# [0.23.0](https://github.com/snomiao/codehost/compare/v0.22.1...v0.23.0) (2026-06-15)
|
|
2
9
|
|
|
3
10
|
|
package/package.json
CHANGED
package/worker/room.ts
CHANGED
|
@@ -16,16 +16,33 @@ interface Attachment {
|
|
|
16
16
|
lastSeen: number;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
/** How
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* cadences are deliberately slow — a hidden Chrome tab's throttled timers
|
|
24
|
-
* (1/min) must still beat STALE_MS, or background tabs churn evict/reconnect
|
|
25
|
-
* cycles all day. */
|
|
26
|
-
const SWEEP_MS = 20_000;
|
|
19
|
+
/** How long a socket may go silent before eviction. Clients heartbeat every
|
|
20
|
+
* ~25s (HEARTBEAT_MS in signaling-client.ts); allow ~2 misses, so a crashed
|
|
21
|
+
* peer drops out within ~65s+. A hidden Chrome tab's throttled timers (1/min)
|
|
22
|
+
* must still beat STALE_MS, or background tabs churn evict/reconnect all day. */
|
|
27
23
|
const STALE_MS = 65_000;
|
|
28
24
|
|
|
25
|
+
/** The sweep alarm scans for dead sockets, and every firing is a billable DO
|
|
26
|
+
* request. A room with one always-on daemon never goes idle, so a fixed-cadence
|
|
27
|
+
* sweep would wake the DO forever — the dominant signaling cost. Instead the
|
|
28
|
+
* interval backs off exponentially with NO upper bound: it starts at
|
|
29
|
+
* SWEEP_MIN_MS so a just-changed room evicts promptly, doubles after every no-op
|
|
30
|
+
* sweep, and resets to the floor whenever a peer joins or a stale socket is
|
|
31
|
+
* evicted. So a long-stable room's sweep cost trends to zero — past
|
|
32
|
+
* SWEEP_STOP_MS it stops arming the alarm entirely. The trade-off: a
|
|
33
|
+
* hard-killed peer can then linger until the edge notices the dead socket or
|
|
34
|
+
* someone new joins the room (cosmetic — a graceful close still evicts
|
|
35
|
+
* immediately via webSocketClose). The interval is persisted (DO storage) so it
|
|
36
|
+
* survives hibernation between alarms. */
|
|
37
|
+
const SWEEP_MIN_MS = 20_000;
|
|
38
|
+
const SWEEP_MAX_MS = Infinity;
|
|
39
|
+
/** Overflow/sanity guard for the unbounded backoff: once the doubled interval
|
|
40
|
+
* passes a day, stop arming the sweep rather than hand setAlarm an ever-growing
|
|
41
|
+
* (eventually non-finite) timestamp. A peer join revives sweeping at the floor
|
|
42
|
+
* via ensureSweep, so phantom cleanup resumes whenever the room is used again. */
|
|
43
|
+
const SWEEP_STOP_MS = 24 * 60 * 60 * 1000;
|
|
44
|
+
const SWEEP_KEY = "sweepMs";
|
|
45
|
+
|
|
29
46
|
/**
|
|
30
47
|
* One Durable Object instance per token-room. Holds the live WebSocket
|
|
31
48
|
* connections, keeps a registry of who is present, and relays WebRTC signals
|
|
@@ -117,9 +134,17 @@ export class Room implements DurableObject {
|
|
|
117
134
|
}
|
|
118
135
|
}
|
|
119
136
|
if (evicted) this.broadcastPeers();
|
|
120
|
-
//
|
|
121
|
-
if (this.state.getWebSockets().length
|
|
122
|
-
|
|
137
|
+
// Idle room: stop sweeping and let the DO hibernate.
|
|
138
|
+
if (this.state.getWebSockets().length === 0) return;
|
|
139
|
+
// Stable sweep -> double the interval (capped); an eviction means the room is
|
|
140
|
+
// changing, so reset to the floor and stay vigilant.
|
|
141
|
+
const prev = (await this.state.storage.get<number>(SWEEP_KEY)) ?? SWEEP_MIN_MS;
|
|
142
|
+
const next = evicted ? SWEEP_MIN_MS : Math.min(prev * 2, SWEEP_MAX_MS);
|
|
143
|
+
await this.state.storage.put(SWEEP_KEY, next);
|
|
144
|
+
// Unbounded backoff: past the stop horizon, leave the alarm unset — a long
|
|
145
|
+
// stable room sweeps no more. A join (ensureSweep) or eviction revives it.
|
|
146
|
+
if (next <= SWEEP_STOP_MS) {
|
|
147
|
+
await this.state.storage.setAlarm(now + next);
|
|
123
148
|
}
|
|
124
149
|
}
|
|
125
150
|
|
|
@@ -151,11 +176,12 @@ export class Room implements DurableObject {
|
|
|
151
176
|
return att;
|
|
152
177
|
}
|
|
153
178
|
|
|
154
|
-
/**
|
|
179
|
+
/** (Re)arm the sweep at the floor cadence. Called when a peer joins: a roster
|
|
180
|
+
* change should be re-checked promptly, so reset the backoff and pull the
|
|
181
|
+
* alarm in even if a (backed-off) one is already pending. */
|
|
155
182
|
private async ensureSweep(): Promise<void> {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
183
|
+
await this.state.storage.put(SWEEP_KEY, SWEEP_MIN_MS);
|
|
184
|
+
await this.state.storage.setAlarm(Date.now() + SWEEP_MIN_MS);
|
|
159
185
|
}
|
|
160
186
|
|
|
161
187
|
private findByPeerId(peerId: string): WebSocket | null {
|