castle-web-sdk 0.4.20 → 0.4.22

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.
@@ -62,6 +62,7 @@ export interface CommandParams {
62
62
  "deckStorage.load": Record<string, never>;
63
63
  "deckStorage.update": {
64
64
  updates: StorageUpdate[];
65
+ unload?: boolean;
65
66
  };
66
67
  "sharedDeckStorage.load": {
67
68
  scope: SharedScope;
@@ -71,6 +72,7 @@ export interface CommandParams {
71
72
  "sharedDeckStorage.update": {
72
73
  scope: SharedScope;
73
74
  updates: StorageUpdate[];
75
+ unload?: boolean;
74
76
  };
75
77
  "leaderboard.fetch": {
76
78
  variable: string;
package/dist/storage.js CHANGED
@@ -1,6 +1,10 @@
1
1
  import { CastleError } from "./errors";
2
2
  import { hostRequest } from "./transport";
3
- const FLUSH_INTERVAL_MS = 2000;
3
+ // The child coalesces writes -- a frame can set the same key many times -- and
4
+ // hands them to the host on this interval. The host, not the deck, talks to the
5
+ // server and owns retry: it lives in the page, so it is still alive to finish a
6
+ // write while the deck's frame is being torn down.
7
+ const FLUSH_INTERVAL_MS = 200;
4
8
  // Per-player private storage. The host stamps deckId/sessionId, so one deck
5
9
  // session = one stable blob: load once, then serve reads from cache and batch
6
10
  // writes on a 2s flush. Dirty writes overlay the server blob so an in-flight
@@ -38,16 +42,17 @@ class PrivateStorageImpl {
38
42
  this.cache = decodeStorageBlob(blob, "Storage.get");
39
43
  this.overlayDirty();
40
44
  }
41
- async flush() {
45
+ async flush(unload = false) {
42
46
  if (this.dirty.size === 0)
43
47
  return;
44
48
  const snapshot = new Map(this.dirty);
45
- const { blob } = await hostRequest("deckStorage.update", {
49
+ await hostRequest("deckStorage.update", {
46
50
  updates: updatesFromDirty(snapshot),
51
+ unload,
47
52
  });
48
- this.cache = decodeStorageBlob(blob, "Storage.flush");
53
+ // Staged, not stored: the host has taken ownership, so these stop being the
54
+ // deck's problem. `cache` already carries them from the write.
49
55
  clearAcknowledgedDirty(this.dirty, snapshot);
50
- this.overlayDirty();
51
56
  }
52
57
  overlayDirty() {
53
58
  for (const [key, encoded] of this.dirty) {
@@ -67,7 +72,7 @@ class PrivateStorageImpl {
67
72
  }, FLUSH_INTERVAL_MS);
68
73
  }
69
74
  flushNow() {
70
- void this.flush();
75
+ void this.flush(true);
71
76
  }
72
77
  }
73
78
  // Cross-player storage. Writes always target the current player (the host
@@ -155,18 +160,19 @@ class SharedStorageImpl {
155
160
  read.resolve(value);
156
161
  }
157
162
  }
158
- async flush() {
163
+ async flush(unload = false) {
159
164
  if (this.dirtyBuckets.size === 0)
160
165
  return;
161
- const tasks = Array.from(this.dirtyBuckets, ([bucketKey, dirty]) => this.flushBucket(bucketKey, new Map(dirty)));
166
+ const tasks = Array.from(this.dirtyBuckets, ([bucketKey, dirty]) => this.flushBucket(bucketKey, new Map(dirty), unload));
162
167
  await Promise.all(tasks);
163
168
  }
164
- async flushBucket(bucketKey, snapshot) {
169
+ async flushBucket(bucketKey, snapshot, unload = false) {
165
170
  if (snapshot.size === 0)
166
171
  return;
167
172
  await hostRequest("sharedDeckStorage.update", {
168
173
  scope: scopeFromWriteKey(bucketKey),
169
174
  updates: updatesFromDirty(snapshot),
175
+ unload,
170
176
  });
171
177
  const dirty = this.dirtyBuckets.get(bucketKey);
172
178
  if (!dirty)
@@ -185,7 +191,7 @@ class SharedStorageImpl {
185
191
  }, FLUSH_INTERVAL_MS);
186
192
  }
187
193
  flushNow() {
188
- void this.flush().catch(reportSharedStorageError);
194
+ void this.flush(true).catch(reportSharedStorageError);
189
195
  }
190
196
  }
191
197
  // Writes batch on a timer, so leaving the page inside that window would lose
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "castle-web-sdk",
3
- "version": "0.4.20",
3
+ "version": "0.4.22",
4
4
  "type": "module",
5
5
  "main": "dist/castle.js",
6
6
  "types": "dist/castle.d.ts",