capnweb-experimental-hibernation 0.6.4 → 0.6.5

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.
@@ -2853,15 +2853,16 @@ var RpcSessionImpl = class {
2853
2853
  }
2854
2854
  sendCall(id, path, args) {
2855
2855
  if (this.abortReason) throw this.abortReason;
2856
- let entry = new ImportTableEntry(this, this.imports.length, false);
2857
- this.imports.push(entry);
2858
2856
  let value = ["pipeline", id, path];
2859
2857
  if (args) {
2860
2858
  let devalue = Devaluator.devaluate(args.value, void 0, this, args);
2861
2859
  value.push(devalue[0]);
2862
2860
  }
2863
- this.send(["push", entry.importId, value]);
2864
- this.trace("sendCall", { importId: entry.importId, targetImportId: id, pathLength: path.length, hasArgs: !!args });
2861
+ const importId = this.imports.length;
2862
+ this.send(["push", importId, value]);
2863
+ const entry = new ImportTableEntry(this, importId, false);
2864
+ this.imports.push(entry);
2865
+ this.trace("sendCall", { importId, targetImportId: id, pathLength: path.length, hasArgs: !!args });
2865
2866
  return new RpcImportHook(
2866
2867
  /*isPromise=*/
2867
2868
  true,
@@ -2870,7 +2871,11 @@ var RpcSessionImpl = class {
2870
2871
  }
2871
2872
  sendStream(id, path, args) {
2872
2873
  if (this.abortReason) throw this.abortReason;
2873
- let importId = this.imports.length;
2874
+ let value = ["pipeline", id, path];
2875
+ let devalue = Devaluator.devaluate(args.value, void 0, this, args);
2876
+ value.push(devalue[0]);
2877
+ const importId = this.imports.length;
2878
+ let size = this.send(["stream", importId, value]);
2874
2879
  let entry = new ImportTableEntry(
2875
2880
  this,
2876
2881
  importId,
@@ -2880,10 +2885,6 @@ var RpcSessionImpl = class {
2880
2885
  entry.remoteRefcount = 0;
2881
2886
  entry.localRefcount = 1;
2882
2887
  this.imports.push(entry);
2883
- let value = ["pipeline", id, path];
2884
- let devalue = Devaluator.devaluate(args.value, void 0, this, args);
2885
- value.push(devalue[0]);
2886
- let size = this.send(["stream", importId, value]);
2887
2888
  this.trace("sendStream", { importId, targetImportId: id, pathLength: path.length, size });
2888
2889
  let promise = entry.awaitResolution().then(
2889
2890
  (p) => {
@@ -2905,18 +2906,19 @@ var RpcSessionImpl = class {
2905
2906
  throw this.abortReason;
2906
2907
  }
2907
2908
  let devaluedCaptures = captures.map((hook) => {
2908
- let importId = this.getImport(hook);
2909
- if (importId !== void 0) {
2910
- return ["import", importId];
2909
+ let importId2 = this.getImport(hook);
2910
+ if (importId2 !== void 0) {
2911
+ return ["import", importId2];
2911
2912
  } else {
2912
2913
  return ["export", this.exportStub(hook)];
2913
2914
  }
2914
2915
  });
2915
2916
  let value = ["remap", id, path, devaluedCaptures, instructions];
2916
- let entry = new ImportTableEntry(this, this.imports.length, false);
2917
+ const importId = this.imports.length;
2918
+ this.send(["push", importId, value]);
2919
+ const entry = new ImportTableEntry(this, importId, false);
2917
2920
  this.imports.push(entry);
2918
- this.send(["push", entry.importId, value]);
2919
- this.trace("sendMap", { importId: entry.importId, targetImportId: id, pathLength: path.length, captureCount: captures.length });
2921
+ this.trace("sendMap", { importId, targetImportId: id, pathLength: path.length, captureCount: captures.length });
2920
2922
  return new RpcImportHook(
2921
2923
  /*isPromise=*/
2922
2924
  true,
@@ -2989,8 +2991,9 @@ var RpcSessionImpl = class {
2989
2991
  case "push":
2990
2992
  if (msg.length > 2 && typeof msg[1] === "number") {
2991
2993
  let exportId = msg[1];
2994
+ let sourceExpr = cloneRpcExpr(msg[2]);
2992
2995
  if (containsImportedCapabilityReference(msg[2])) {
2993
- this.importReplays.push({ expr: cloneRpcExpr(msg[2]) });
2996
+ this.importReplays.push({ expr: sourceExpr });
2994
2997
  this.trace("readLoop.push.recordImportReplay", {
2995
2998
  exportId,
2996
2999
  replayCount: this.importReplays.length
@@ -3002,7 +3005,7 @@ var RpcSessionImpl = class {
3002
3005
  this.replacePositiveExport(exportId, {
3003
3006
  hook,
3004
3007
  refcount: 1,
3005
- sourceExpr: cloneRpcExpr(msg[2])
3008
+ sourceExpr
3006
3009
  });
3007
3010
  this.trace("readLoop.push", { exportId, hookType: hook.constructor?.name ?? null });
3008
3011
  continue;
@@ -3011,13 +3014,14 @@ var RpcSessionImpl = class {
3011
3014
  case "stream": {
3012
3015
  if (msg.length > 2 && typeof msg[1] === "number") {
3013
3016
  let exportId = msg[1];
3017
+ let sourceExpr = cloneRpcExpr(msg[2]);
3014
3018
  let payload = this.evaluateWithCurrentProvenance(msg[2]);
3015
3019
  let hook = new PayloadStubHook(payload);
3016
3020
  hook.ignoreUnhandledRejections();
3017
3021
  this.replacePositiveExport(exportId, {
3018
3022
  hook,
3019
3023
  refcount: 1,
3020
- sourceExpr: cloneRpcExpr(msg[2]),
3024
+ sourceExpr,
3021
3025
  autoRelease: true
3022
3026
  });
3023
3027
  this.trace("readLoop.stream", { exportId, hookType: hook.constructor?.name ?? null });
@@ -3413,6 +3417,11 @@ async function __experimental_newHibernatableWebSocketRpcSession(webSocket, loca
3413
3417
  },
3414
3418
  handleClose(code, reason, wasClean) {
3415
3419
  transport.notifyClosed(code, reason, wasClean);
3420
+ if (options.sessionStore) {
3421
+ options.sessionStore.delete(sessionId).catch((err) => {
3422
+ console.error(`[capnweb] Failed to delete session ${sessionId} from store:`, err);
3423
+ });
3424
+ }
3416
3425
  },
3417
3426
  handleError(error) {
3418
3427
  transport.notifyError(error);
@@ -3421,24 +3430,35 @@ async function __experimental_newHibernatableWebSocketRpcSession(webSocket, loca
3421
3430
  async function persistSnapshot() {
3422
3431
  try {
3423
3432
  let snap = rpc.__experimental_snapshot();
3424
- webSocket.serializeAttachment?.({
3425
- sessionId,
3426
- version: 1,
3427
- snapshot: snap
3428
- });
3429
3433
  if (options.sessionStore) {
3430
3434
  await options.sessionStore.save(sessionId, snap);
3431
3435
  }
3436
+ let capnwebData = options.sessionStore ? { sessionId, version: 1 } : { sessionId, version: 1, snapshot: snap };
3437
+ let existing = webSocket.deserializeAttachment?.() ?? {};
3438
+ if (typeof existing !== "object" || existing === null) existing = {};
3439
+ webSocket.serializeAttachment?.({ ...existing, __capnweb: capnwebData });
3432
3440
  } catch (err) {
3433
3441
  transport.abort?.(err);
3434
3442
  }
3435
3443
  }
3436
3444
  }
3445
+ async function __experimental_cleanupOrphanedSessions(webSockets, sessionStore) {
3446
+ if (!sessionStore.deleteOrphans) return 0;
3447
+ const liveIds = /* @__PURE__ */ new Set();
3448
+ for (const ws of webSockets) {
3449
+ const attachment = getAttachment(ws);
3450
+ if (attachment?.sessionId) {
3451
+ liveIds.add(attachment.sessionId);
3452
+ }
3453
+ }
3454
+ return sessionStore.deleteOrphans(liveIds);
3455
+ }
3437
3456
  async function __experimental_resumeHibernatableWebSocketRpcSession(webSocket, localMain, options) {
3438
3457
  return __experimental_newHibernatableWebSocketRpcSession(webSocket, localMain, options);
3439
3458
  }
3440
3459
  function getAttachment(webSocket) {
3441
- let attachment = webSocket.deserializeAttachment?.();
3460
+ let raw = webSocket.deserializeAttachment?.();
3461
+ let attachment = raw?.__capnweb ?? raw;
3442
3462
  if (attachment?.version === 1 && typeof attachment.sessionId === "string") {
3443
3463
  return attachment;
3444
3464
  }
@@ -3517,7 +3537,11 @@ var WebSocketTransport = class {
3517
3537
  if (reason instanceof Error) {
3518
3538
  message = reason.message;
3519
3539
  } else {
3520
- message = `${reason}`;
3540
+ try {
3541
+ message = JSON.stringify(reason);
3542
+ } catch {
3543
+ message = `${reason}`;
3544
+ }
3521
3545
  }
3522
3546
  this.#webSocket.close(3e3, message);
3523
3547
  if (!this.#error) {
@@ -3602,7 +3626,11 @@ var HibernatableWebSocketTransport = class {
3602
3626
  if (reason instanceof Error) {
3603
3627
  message = reason.message;
3604
3628
  } else {
3605
- message = `${reason}`;
3629
+ try {
3630
+ message = JSON.stringify(reason);
3631
+ } catch {
3632
+ message = `${reason}`;
3633
+ }
3606
3634
  }
3607
3635
  try {
3608
3636
  this.webSocket.close(3e3, message);
@@ -4194,6 +4222,21 @@ function __experimental_newDurableObjectSessionStore(storage, prefix = "capnweb:
4194
4222
  },
4195
4223
  async delete(sessionId) {
4196
4224
  await storage.delete(`${prefix}${sessionId}`);
4225
+ },
4226
+ async deleteOrphans(liveSessionIds) {
4227
+ if (!storage.list) return 0;
4228
+ const stored = await storage.list({ prefix });
4229
+ const orphanKeys = [];
4230
+ for (const key of stored.keys()) {
4231
+ const sessionId = key.slice(prefix.length);
4232
+ if (!liveSessionIds.has(sessionId)) {
4233
+ orphanKeys.push(key);
4234
+ }
4235
+ }
4236
+ if (orphanKeys.length > 0) {
4237
+ await storage.delete(orphanKeys);
4238
+ }
4239
+ return orphanKeys.length;
4197
4240
  }
4198
4241
  };
4199
4242
  }
@@ -4206,6 +4249,7 @@ var newHttpBatchRpcSession2 = newHttpBatchRpcSession;
4206
4249
  var newMessagePortRpcSession2 = newMessagePortRpcSession;
4207
4250
  var __experimental_newHibernatableWebSocketRpcSession2 = __experimental_newHibernatableWebSocketRpcSession;
4208
4251
  var __experimental_resumeHibernatableWebSocketRpcSession2 = __experimental_resumeHibernatableWebSocketRpcSession;
4252
+ var __experimental_cleanupOrphanedSessions2 = __experimental_cleanupOrphanedSessions;
4209
4253
  var __experimental_debugRpcReference2 = __experimental_debugRpcReference;
4210
4254
  async function newWorkersRpcResponse(request, localMain) {
4211
4255
  if (request.method === "POST") {
@@ -4223,6 +4267,7 @@ exports.RpcPromise = RpcPromise2;
4223
4267
  exports.RpcSession = RpcSession2;
4224
4268
  exports.RpcStub = RpcStub2;
4225
4269
  exports.RpcTarget = RpcTarget4;
4270
+ exports.__experimental_cleanupOrphanedSessions = __experimental_cleanupOrphanedSessions2;
4226
4271
  exports.__experimental_debugRpcReference = __experimental_debugRpcReference2;
4227
4272
  exports.__experimental_newDurableObjectSessionStore = __experimental_newDurableObjectSessionStore;
4228
4273
  exports.__experimental_newHibernatableWebSocketRpcSession = __experimental_newHibernatableWebSocketRpcSession2;