@kraki/head 0.15.2 → 0.15.4

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.
@@ -23,6 +23,22 @@
23
23
  import type Database from 'better-sqlite3';
24
24
  import { decodeFrame, encodeFrame } from '@coinfra/pulse';
25
25
  import { type PulseFrameField, type UnicastEnvelope } from '@kraki/protocol';
26
+ /** GC policy — how aggressively the hub reclaims per-device outbox memory
27
+ * for peers that stay disconnected. Zero disables that step. Defaults tuned
28
+ * for a store-and-forward hub with many long-lived-but-often-offline peers
29
+ * (browser tabs closed, phones off, iPad in a drawer). See spec §11. */
30
+ export interface PulseHubGcConfig {
31
+ /** After this many ms Disconnected, drop the endpoint's non-durable outbox
32
+ * (via `endpoint.purgeNonDurable`). Durable entries survive; they persist
33
+ * in `pulse_meta` via `snapshotDurable`. Default 5 * 60_000 (5 min). */
34
+ purgeNonDurableAfterMs?: number;
35
+ /** After this many ms Disconnected, drop the endpoint entirely from memory.
36
+ * Durable snapshot remains in SQLite so a future reconnect can rebuild it
37
+ * via `ep()`. Default 24 * 3600_000 (24 h). */
38
+ evictEndpointAfterMs?: number;
39
+ /** How often the GC scan runs. Default 60_000 (1 min). */
40
+ intervalMs?: number;
41
+ }
26
42
  /** How the hub reaches out: send bytes to a device, and resolve where a
27
43
  * delivered payload should be forwarded. Injected so the hub stays decoupled
28
44
  * from the WebSocket layer and testable. */
@@ -46,7 +62,9 @@ export declare class PulseHub {
46
62
  private readonly db;
47
63
  private readonly host;
48
64
  private readonly devices;
49
- constructor(db: Database.Database, host: PulseHubHost);
65
+ private readonly gc;
66
+ private gcTimer;
67
+ constructor(db: Database.Database, host: PulseHubHost, gc?: PulseHubGcConfig);
50
68
  private initSchema;
51
69
  /** Ensure an endpoint exists for a device (restoring from SQLite if present).
52
70
  * head endpoints are durable-supported (head is always-on + has disk). */
@@ -77,6 +95,7 @@ export declare class PulseHub {
77
95
  * be redelivered stale after the target reconnects. */
78
96
  sendToDevice(destDevice: string, payload: Uint8Array, opts?: {
79
97
  durable?: boolean;
98
+ coalesceKey?: string;
80
99
  }): void;
81
100
  private storeOutbox;
82
101
  private unstoreOutbox;
@@ -87,6 +106,29 @@ export declare class PulseHub {
87
106
  recoverOnBoot(): void;
88
107
  /** Test/introspection: how many durable rows are held for a device. */
89
108
  outboxCount(device: string): number;
109
+ /** In-memory endpoint count. Test/introspection. */
110
+ endpointCount(): number;
111
+ /** Stop the periodic GC scan. Call on shutdown. */
112
+ close(): void;
113
+ private startGc;
114
+ /**
115
+ * Two-tier GC per endpoint (see spec §11.4):
116
+ *
117
+ * L1 (purgeNonDurableAfterMs, default 5 min)
118
+ * Endpoint disconnected ≥ L1 → `purgeNonDurable()`. Streaming deltas,
119
+ * idle markers, and other ephemera queued during the offline window
120
+ * get dropped. Durable messages (delete_session) survive.
121
+ *
122
+ * L2 (evictEndpointAfterMs, default 24 h)
123
+ * Endpoint disconnected ≥ L2 → delete the in-memory endpoint entirely.
124
+ * Durable outbox rows remain in SQLite (via `pulse_meta` from prior
125
+ * `snapshotDurable` writes), so a future reconnect rebuilds the
126
+ * endpoint via `ep()` and picks them up.
127
+ *
128
+ * Only Disconnected endpoints are candidates. Endpoints without a
129
+ * `disconnectedAtMs` (never disconnected in this run) are skipped.
130
+ */
131
+ gcTick(): void;
90
132
  }
91
133
  export { decodeFrame, encodeFrame };
92
134
  export type { UnicastEnvelope };
package/dist/pulse-hub.js CHANGED
@@ -22,16 +22,26 @@
22
22
  */
23
23
  import { decodeFrame, encodeFrame, Endpoint } from '@coinfra/pulse';
24
24
  import { HEAD_PULSE_TARGET } from '@kraki/protocol';
25
+ import { getLogger } from './logger.js';
26
+ const DEFAULT_GC = {
27
+ purgeNonDurableAfterMs: 5 * 60_000,
28
+ evictEndpointAfterMs: 24 * 3600_000,
29
+ intervalMs: 60_000,
30
+ };
25
31
  const b64encode = (u) => Buffer.from(u).toString('base64');
26
32
  const b64decode = (s) => new Uint8Array(Buffer.from(s, 'base64'));
27
33
  export class PulseHub {
28
34
  db;
29
35
  host;
30
36
  devices = new Map();
31
- constructor(db, host) {
37
+ gc;
38
+ gcTimer = null;
39
+ constructor(db, host, gc) {
32
40
  this.db = db;
33
41
  this.host = host;
42
+ this.gc = { ...DEFAULT_GC, ...(gc ?? {}) };
34
43
  this.initSchema();
44
+ this.startGc();
35
45
  }
36
46
  initSchema() {
37
47
  this.db.exec(`CREATE TABLE IF NOT EXISTS pulse_outbox (
@@ -115,9 +125,12 @@ export class PulseHub {
115
125
  }
116
126
  else {
117
127
  // Store-and-forward bridge: forward the reliable payload onto each
118
- // destination device's endpoint, preserving the durable intent.
128
+ // destination device's endpoint, preserving durable intent AND the
129
+ // send-time coalesce hint (pulse §12) so state-covering streams
130
+ // (deltas, card state) collapse on the arm-facing outbox if the arm
131
+ // is offline, instead of bursting on reconnect.
119
132
  for (const dest of dests ?? [])
120
- this.forward(dest, e.payload, e.durable);
133
+ this.forward(dest, e.payload, e.durable, e.coalesceKey);
121
134
  }
122
135
  break;
123
136
  case 'store':
@@ -134,9 +147,9 @@ export class PulseHub {
134
147
  /** Forward a payload onto the destination device's outbound endpoint. If the
135
148
  * destination is offline, the pulse endpoint keeps it in its outbox (durable
136
149
  * → also persisted to SQLite via the store effect) and resends on reconnect. */
137
- forward(destDevice, payload, durable) {
150
+ forward(destDevice, payload, durable, coalesceKey) {
138
151
  const d = this.ep(destDevice);
139
- const { effects } = d.endpoint.send(payload, { durable });
152
+ const { effects } = d.endpoint.send(payload, { durable, coalesceKey });
140
153
  // The destination endpoint's transmits go to the destination device; its
141
154
  // deliveries would bridge back (not used in one-way flows). No secondary
142
155
  // dest — a forwarded message is terminal at the destination device.
@@ -149,7 +162,7 @@ export class PulseHub {
149
162
  * head-originated control (e.g. "device X joined") is ephemeral and must not
150
163
  * be redelivered stale after the target reconnects. */
151
164
  sendToDevice(destDevice, payload, opts) {
152
- this.forward(destDevice, payload, opts?.durable ?? false);
165
+ this.forward(destDevice, payload, opts?.durable ?? false, opts?.coalesceKey);
153
166
  }
154
167
  // ── SQLite persistence ──────────────────────────────────────────────────────
155
168
  storeOutbox(device, seq, payload, dest) {
@@ -166,9 +179,15 @@ export class PulseHub {
166
179
  const d = this.devices.get(device);
167
180
  if (!d)
168
181
  return;
182
+ // Use snapshotDurable() (pulse §11.3) — persisting non-durable entries to
183
+ // disk both violates their "in-memory only, may be lost on restart"
184
+ // contract AND is the exact root cause of the 2026-07-07 head OOM
185
+ // (each save re-serialized an ever-growing in-memory outbox for offline
186
+ // peers). Durable entries (currently just delete_session in kraki) are
187
+ // preserved so a future reconnect delivers them.
169
188
  this.db
170
189
  .prepare('INSERT OR REPLACE INTO pulse_meta (device, snapshot) VALUES (?, ?)')
171
- .run(device, JSON.stringify(d.endpoint.snapshot()));
190
+ .run(device, JSON.stringify(d.endpoint.snapshotDurable()));
172
191
  }
173
192
  loadSnapshot(device) {
174
193
  const row = this.db.prepare('SELECT snapshot FROM pulse_meta WHERE device = ?').get(device);
@@ -188,6 +207,84 @@ export class PulseHub {
188
207
  .get(device);
189
208
  return row.n;
190
209
  }
210
+ /** In-memory endpoint count. Test/introspection. */
211
+ endpointCount() {
212
+ return this.devices.size;
213
+ }
214
+ /** Stop the periodic GC scan. Call on shutdown. */
215
+ close() {
216
+ if (this.gcTimer) {
217
+ clearInterval(this.gcTimer);
218
+ this.gcTimer = null;
219
+ }
220
+ }
221
+ // ── GC scan (spec §11.4) ────────────────────────────────────────────────
222
+ startGc() {
223
+ if (this.gc.intervalMs <= 0)
224
+ return;
225
+ this.gcTimer = setInterval(() => {
226
+ try {
227
+ this.gcTick();
228
+ }
229
+ catch (err) {
230
+ getLogger().error('pulse-hub gc tick failed', { error: err.message });
231
+ }
232
+ }, this.gc.intervalMs);
233
+ if (this.gcTimer && typeof this.gcTimer.unref === 'function') {
234
+ this.gcTimer.unref();
235
+ }
236
+ }
237
+ /**
238
+ * Two-tier GC per endpoint (see spec §11.4):
239
+ *
240
+ * L1 (purgeNonDurableAfterMs, default 5 min)
241
+ * Endpoint disconnected ≥ L1 → `purgeNonDurable()`. Streaming deltas,
242
+ * idle markers, and other ephemera queued during the offline window
243
+ * get dropped. Durable messages (delete_session) survive.
244
+ *
245
+ * L2 (evictEndpointAfterMs, default 24 h)
246
+ * Endpoint disconnected ≥ L2 → delete the in-memory endpoint entirely.
247
+ * Durable outbox rows remain in SQLite (via `pulse_meta` from prior
248
+ * `snapshotDurable` writes), so a future reconnect rebuilds the
249
+ * endpoint via `ep()` and picks them up.
250
+ *
251
+ * Only Disconnected endpoints are candidates. Endpoints without a
252
+ * `disconnectedAtMs` (never disconnected in this run) are skipped.
253
+ */
254
+ gcTick() {
255
+ const now = this.host.now();
256
+ let purged = 0;
257
+ let evicted = 0;
258
+ for (const [deviceId, d] of this.devices) {
259
+ const disconnectedAt = d.endpoint.disconnectedAtMs;
260
+ if (d.endpoint.link !== 'disconnected' || disconnectedAt === null)
261
+ continue;
262
+ const offlineMs = now - disconnectedAt;
263
+ if (this.gc.evictEndpointAfterMs > 0 && offlineMs >= this.gc.evictEndpointAfterMs) {
264
+ // L2: release the endpoint. Durable state stays in pulse_meta.
265
+ this.devices.delete(deviceId);
266
+ evicted += 1;
267
+ continue;
268
+ }
269
+ if (this.gc.purgeNonDurableAfterMs > 0
270
+ && offlineMs >= this.gc.purgeNonDurableAfterMs
271
+ && d.endpoint.nonDurableCount > 0) {
272
+ // L1: drop non-durable outbox entries only.
273
+ const { droppedSeqs } = d.endpoint.purgeNonDurable('gc-idle');
274
+ if (droppedSeqs.length > 0) {
275
+ purged += droppedSeqs.length;
276
+ this.saveSnapshot(deviceId);
277
+ }
278
+ }
279
+ }
280
+ if (purged > 0 || evicted > 0) {
281
+ getLogger().info('pulse-hub gc', {
282
+ purgedSeqs: purged,
283
+ evictedEndpoints: evicted,
284
+ totalEndpoints: this.devices.size,
285
+ });
286
+ }
287
+ }
191
288
  }
192
289
  // Re-export the frame codec for the server to build/inspect pulse envelopes.
193
290
  export { decodeFrame, encodeFrame };
@@ -1 +1 @@
1
- {"version":3,"file":"pulse-hub.js","sourceRoot":"","sources":["../src/pulse-hub.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pulse-hub.js","sourceRoot":"","sources":["../src/pulse-hub.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kraki/head",
3
- "version": "0.15.2",
3
+ "version": "0.15.4",
4
4
  "description": "Kraki relay server — the brain that routes messages between tentacles and apps",
5
5
  "repository": {
6
6
  "type": "git",
@@ -24,14 +24,14 @@
24
24
  "kraki-relay": "dist/cli.js"
25
25
  },
26
26
  "dependencies": {
27
- "@coinfra/pulse": "^0.1.2",
27
+ "@coinfra/pulse": "^0.3.0",
28
28
  "better-sqlite3": "^11.0.0",
29
29
  "dotenv": "^17.3.1",
30
30
  "uuid": "^13.0.0",
31
31
  "web-push": "^3.6.7",
32
32
  "ws": "^8.19.0",
33
33
  "@kraki/crypto": "0.2.1",
34
- "@kraki/protocol": "0.17.0"
34
+ "@kraki/protocol": "0.18.0"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@types/better-sqlite3": "^7.6.0",