@instantdb/core 0.22.57 → 0.22.58

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 (60) hide show
  1. package/__tests__/src/Reactor.test.js +97 -21
  2. package/__tests__/src/utils/PersistedObject.test.ts +383 -0
  3. package/dist/commonjs/InMemoryStorage.d.ts +11 -0
  4. package/dist/commonjs/InMemoryStorage.d.ts.map +1 -0
  5. package/dist/commonjs/InMemoryStorage.js +48 -0
  6. package/dist/commonjs/InMemoryStorage.js.map +1 -0
  7. package/dist/commonjs/IndexedDBStorage.d.ts +10 -3
  8. package/dist/commonjs/IndexedDBStorage.d.ts.map +1 -1
  9. package/dist/commonjs/IndexedDBStorage.js +254 -8
  10. package/dist/commonjs/IndexedDBStorage.js.map +1 -1
  11. package/dist/commonjs/Reactor.d.ts +7 -16
  12. package/dist/commonjs/Reactor.d.ts.map +1 -1
  13. package/dist/commonjs/Reactor.js +199 -149
  14. package/dist/commonjs/Reactor.js.map +1 -1
  15. package/dist/commonjs/SyncTable.d.ts +3 -1
  16. package/dist/commonjs/SyncTable.d.ts.map +1 -1
  17. package/dist/commonjs/SyncTable.js +194 -168
  18. package/dist/commonjs/SyncTable.js.map +1 -1
  19. package/dist/commonjs/index.d.ts +2 -1
  20. package/dist/commonjs/index.d.ts.map +1 -1
  21. package/dist/commonjs/index.js +3 -1
  22. package/dist/commonjs/index.js.map +1 -1
  23. package/dist/commonjs/utils/PersistedObject.d.ts +73 -29
  24. package/dist/commonjs/utils/PersistedObject.d.ts.map +1 -1
  25. package/dist/commonjs/utils/PersistedObject.js +366 -77
  26. package/dist/commonjs/utils/PersistedObject.js.map +1 -1
  27. package/dist/esm/InMemoryStorage.d.ts +11 -0
  28. package/dist/esm/InMemoryStorage.d.ts.map +1 -0
  29. package/dist/esm/InMemoryStorage.js +45 -0
  30. package/dist/esm/InMemoryStorage.js.map +1 -0
  31. package/dist/esm/IndexedDBStorage.d.ts +10 -3
  32. package/dist/esm/IndexedDBStorage.d.ts.map +1 -1
  33. package/dist/esm/IndexedDBStorage.js +254 -8
  34. package/dist/esm/IndexedDBStorage.js.map +1 -1
  35. package/dist/esm/Reactor.d.ts +7 -16
  36. package/dist/esm/Reactor.d.ts.map +1 -1
  37. package/dist/esm/Reactor.js +199 -149
  38. package/dist/esm/Reactor.js.map +1 -1
  39. package/dist/esm/SyncTable.d.ts +3 -1
  40. package/dist/esm/SyncTable.d.ts.map +1 -1
  41. package/dist/esm/SyncTable.js +194 -168
  42. package/dist/esm/SyncTable.js.map +1 -1
  43. package/dist/esm/index.d.ts +2 -1
  44. package/dist/esm/index.d.ts.map +1 -1
  45. package/dist/esm/index.js +4 -1
  46. package/dist/esm/index.js.map +1 -1
  47. package/dist/esm/utils/PersistedObject.d.ts +73 -29
  48. package/dist/esm/utils/PersistedObject.d.ts.map +1 -1
  49. package/dist/esm/utils/PersistedObject.js +364 -76
  50. package/dist/esm/utils/PersistedObject.js.map +1 -1
  51. package/dist/standalone/index.js +1978 -1567
  52. package/dist/standalone/index.umd.cjs +3 -3
  53. package/package.json +2 -2
  54. package/src/InMemoryStorage.ts +34 -0
  55. package/src/IndexedDBStorage.ts +281 -9
  56. package/src/Reactor.js +212 -184
  57. package/src/SyncTable.ts +220 -191
  58. package/src/index.ts +8 -0
  59. package/src/utils/PersistedObject.ts +480 -109
  60. package/src/InMemoryStorage.js +0 -14
@@ -1 +1 @@
1
- {"version":3,"file":"PersistedObject.d.ts","sourceRoot":"","sources":["../../../src/utils/PersistedObject.ts"],"names":[],"mappings":"AAyBA,qBAAa,eAAe,CAAC,CAAC;IAC5B,KAAK,QAAM;IACX,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,CAAC,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;IACzD,UAAU,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;IAC9B,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE,CAAC,CAAC;IAChB,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,GAAG,CAAC;IAC7B,KAAK,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,CAAC,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,eAAe,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,IAAI,GAAG,MAAM,CAAC,OAAO,CAAQ;gBAGtC,SAAS,EAAE,OAAO,EAClB,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,CAAC;IACf;;;;OAIG;IACH,OAAO,EAAE,CAAC,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI,EACvD,SAAS,IAAI,GAAG,CAAC,KAAG,GAEnB,EACD,KAAK,IAAI,GAAG,GAAG,KAAG,CAEjB,EACD,cAAc,SAAM,EACpB,qBAAqB,SAAO;IAoBxB,eAAe;IASf,KAAK;IAaL,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAUpC,SAAS;IAIT,OAAO;IAID,WAAW;IAUjB,eAAe;IAQT,KAAK;IAQX,eAAe,CAAC,EAAE,KAAA;IAelB,GAAG,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,EAAE,MAAM,IAAI,GAAG,CAAC;IAc1C,SAAS,CAAC,EAAE,KAAA;CAQb"}
1
+ {"version":3,"file":"PersistedObject.d.ts","sourceRoot":"","sources":["../../../src/utils/PersistedObject.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAUvC,eAAO,MAAM,QAAQ,WAAW,CAAC;AAEjC,MAAM,MAAM,UAAU,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhF,MAAM,MAAM,IAAI,CAAC,CAAC,SAAS,MAAM,IAAI;IACnC,OAAO,EAAE,MAAM,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,IAAI,GAAG,WAAW,GAAG,UAAU,CAAC;AAExE,8BAAsB,gBAAgB;gBACxB,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,yBAAyB;IAC/D,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAC3C,QAAQ,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAC/C,QAAQ,CAAC,QAAQ,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IACrE,QAAQ,CAAC,UAAU,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;CACzC;AAED,MAAM,MAAM,MAAM,GAAG;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,WAAW,IAAI;IACpC,SAAS,EAAE,gBAAgB,CAAC;IAC5B;;;OAGG;IACH,KAAK,EAAE,CACL,GAAG,EAAE,CAAC,EACN,WAAW,EAAE,CAAC,GAAG,IAAI,GAAG,SAAS,EACjC,aAAa,EAAE,CAAC,GAAG,IAAI,GAAG,SAAS,KAChC,CAAC,CAAC;IACP,SAAS,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,WAAW,CAAC;IAC7C,KAAK,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,WAAW,KAAK,CAAC,CAAC;IACzC,UAAU,EAAE,CAAC,CAAC,EAAE,WAAW,KAAK,MAAM,CAAC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC3C,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAClD,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CAC/C,CAAC;AAEF,qBAAa,eAAe,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,WAAW;IAC3D,YAAY,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3B,OAAO,CAAC,KAAK,CAAM;IACnB,OAAO,CAAC,UAAU,CAAmB;IACrC,OAAO,CAAC,MAAM,CAAkD;IAChE,OAAO,CAAC,SAAS,CAAoC;IACrD,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,sBAAsB,CAAS;IACvC,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,YAAY,CAAwB;IAC5C,OAAO,CAAC,WAAW,CAA4C;IAC/D,OAAO,CAAC,IAAI,CAAS;IAErB,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC;IACtD,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,KAAK,CAaX;IACF,OAAO,CAAC,OAAO,CAAS;gBAEZ,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,WAAW,CAAC;YAmB3B,SAAS;YA2BT,QAAQ;YAaR,YAAY;YAKZ,eAAe;YAWf,eAAe;IAchB,gBAAgB,CAAC,CAAC,EAAE,CAAC;IASrB,iBAAiB;IAMvB,SAAS,CAAC,CAAC,EAAE,CAAC;YAMP,QAAQ;IAqBtB,OAAO,CAAC,eAAe;IAkGjB,KAAK;YAUG,GAAG;IA6HjB,EAAE;IAgBF,OAAO,CAAC,eAAe;IAmBvB,OAAO;IAOA,aAAa,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,IAAI;IA6BlD,SAAS,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI;CAQnD"}
@@ -23,9 +23,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
23
23
  });
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.PersistedObject = void 0;
26
+ exports.PersistedObject = exports.StorageInterface = exports.META_KEY = void 0;
27
27
  // Uses `requestIdleCallback` if available, otherwise calls the
28
28
  // callback immediately
29
+ const mutative_1 = require("mutative");
29
30
  function safeIdleCallback(cb, timeout) {
30
31
  if (typeof requestIdleCallback === 'undefined') {
31
32
  cb();
@@ -34,92 +35,243 @@ function safeIdleCallback(cb, timeout) {
34
35
  requestIdleCallback(cb, { timeout });
35
36
  }
36
37
  }
38
+ exports.META_KEY = '__meta';
39
+ class StorageInterface {
40
+ constructor(appId, storeName) { }
41
+ }
42
+ exports.StorageInterface = StorageInterface;
37
43
  class PersistedObject {
38
- constructor(persister, key, defaultValue,
39
- /**
40
- * Merges data from storage with in-memory value on load.
41
- * If a value is returned from onMerge, that value that will
42
- * become the current value.
43
- */
44
- onMerge, serialize = (x) => {
45
- return x;
46
- }, parse = (x) => {
47
- return x;
48
- }, saveThrottleMs = 100, idleCallbackMaxWaitMs = 1000) {
44
+ constructor(opts) {
45
+ var _a, _b;
49
46
  this._subs = [];
50
47
  this._nextSave = null;
51
- this._persister = persister;
52
- this._key = key;
53
- this._onMerge = onMerge;
54
- this._loadedCbs = [];
55
- this._isLoading = true;
56
- this.currentValue = defaultValue;
57
- this.serialize = serialize;
58
- this.parse = parse;
59
- this._saveThrottleMs = saveThrottleMs;
60
- this._pendingSaveCbs = [];
48
+ this._nextGc = null;
49
+ this._pendingSaveKeys = new Set();
50
+ this._loadedKeys = new Set();
61
51
  this._version = 0;
62
- this._idleCallbackMaxWaitMs = idleCallbackMaxWaitMs;
63
- this._load();
52
+ this._meta = {
53
+ isLoading: true,
54
+ onLoadCbs: [],
55
+ value: null,
56
+ error: null,
57
+ attempts: 0,
58
+ };
59
+ this._persister = opts.persister;
60
+ this._merge = opts.merge;
61
+ this.serialize = opts.serialize;
62
+ this.parse = opts.parse;
63
+ this._objectSize = opts.objectSize;
64
+ this._log = opts.logger;
65
+ this._saveThrottleMs = (_a = opts.saveThrottleMs) !== null && _a !== void 0 ? _a : 100;
66
+ this._idleCallbackMaxWaitMs = (_b = opts.idleCallbackMaxWaitMs) !== null && _b !== void 0 ? _b : 1000;
67
+ this._gcOpts = opts.gc;
68
+ this.currentValue = {};
69
+ this._loadedKeys = new Set();
70
+ this._loadingKeys = {};
71
+ this._initMeta();
72
+ if (opts.preloadEntryCount) {
73
+ this._preloadEntries(opts.preloadEntryCount);
74
+ }
64
75
  }
65
- _getFromStorage() {
76
+ _initMeta() {
66
77
  return __awaiter(this, void 0, void 0, function* () {
78
+ var _a, _b, _c;
79
+ if (this._meta.loadingPromise) {
80
+ yield this._meta.loadingPromise;
81
+ }
67
82
  try {
68
- return this.parse(yield this._persister.getItem(this._key));
83
+ const p = this._persister.getItem(exports.META_KEY);
84
+ this._meta.loadingPromise = p;
85
+ const v = yield p;
86
+ this._meta.isLoading = false;
87
+ this._meta.error = null;
88
+ this._meta.loadingPromise = null;
89
+ this._meta.attempts = 0;
90
+ const existingObjects = (_b = (_a = this._meta.value) === null || _a === void 0 ? void 0 : _a.objects) !== null && _b !== void 0 ? _b : {};
91
+ const value = v !== null && v !== void 0 ? v : {};
92
+ const objects = (_c = value.objects) !== null && _c !== void 0 ? _c : {};
93
+ // Merge the values from storage with in-memory values
94
+ this._meta.value = Object.assign(Object.assign({}, value), { objects: Object.assign(Object.assign({}, existingObjects), objects) });
69
95
  }
70
96
  catch (e) {
71
- console.error(`Unable to read from storage for key=${this._key}`, e);
72
- return null;
97
+ this._meta.error = e;
98
+ this._meta.attempts++;
99
+ this._meta.loadingPromise = null;
73
100
  }
74
101
  });
75
102
  }
76
- _load() {
103
+ _getMeta() {
77
104
  return __awaiter(this, void 0, void 0, function* () {
78
- const fromStorage = yield this._getFromStorage();
79
- this._isLoading = false;
80
- const mergeResult = this._onMerge(fromStorage, this.currentValue);
81
- if (mergeResult) {
82
- this.currentValue = mergeResult;
105
+ if (this._meta.value) {
106
+ return this._meta.value;
83
107
  }
84
- for (const cb of this._loadedCbs) {
85
- cb();
108
+ if (this._meta.loadingPromise) {
109
+ yield this._meta.loadingPromise;
110
+ return this._meta.value;
86
111
  }
112
+ this._initMeta();
113
+ yield this._meta.loadingPromise;
114
+ return this._meta.value;
87
115
  });
88
116
  }
89
- waitForLoaded() {
117
+ _refreshMeta() {
90
118
  return __awaiter(this, void 0, void 0, function* () {
91
- if (!this._isLoading) {
92
- return;
93
- }
94
- const loadedPromise = new Promise((resolve) => {
95
- this._loadedCbs.push(resolve);
119
+ yield this._initMeta();
120
+ return this._meta.value;
121
+ });
122
+ }
123
+ _preloadEntries(n) {
124
+ return __awaiter(this, void 0, void 0, function* () {
125
+ const meta = yield this.waitForMetaToLoad();
126
+ const entries = Object.entries(meta.objects);
127
+ entries.sort(([_k_a, a_meta], [_k_b, b_meta]) => {
128
+ return b_meta.updatedAt - a_meta.updatedAt;
96
129
  });
97
- yield loadedPromise;
130
+ for (const [k] of entries.slice(0, n)) {
131
+ this._loadKey(k);
132
+ }
133
+ });
134
+ }
135
+ _getFromStorage(key) {
136
+ return __awaiter(this, void 0, void 0, function* () {
137
+ try {
138
+ const data = yield this._persister.getItem(key);
139
+ if (!data) {
140
+ return data;
141
+ }
142
+ const parsed = this.parse(key, data);
143
+ return parsed;
144
+ }
145
+ catch (e) {
146
+ console.error(`Unable to read from storage for key=${key}`, e);
147
+ return null;
148
+ }
98
149
  });
99
150
  }
100
- isLoading() {
101
- return this._isLoading;
151
+ waitForKeyToLoad(k) {
152
+ return __awaiter(this, void 0, void 0, function* () {
153
+ if (this._loadedKeys.has(k)) {
154
+ return this.currentValue[k];
155
+ }
156
+ yield (this._loadingKeys[k] || this._loadKey(k));
157
+ return this.currentValue[k];
158
+ });
102
159
  }
103
- version() {
104
- return this._version;
160
+ // Used for tests
161
+ waitForMetaToLoad() {
162
+ return __awaiter(this, void 0, void 0, function* () {
163
+ return this._getMeta();
164
+ });
105
165
  }
106
- waitForSync() {
166
+ // Unloads the key so that it can be garbage collected, but does not
167
+ // delete it. Removes the key from currentValue.
168
+ unloadKey(k) {
169
+ this._loadedKeys.delete(k);
170
+ delete this._loadingKeys[k];
171
+ delete this.currentValue[k];
172
+ }
173
+ _loadKey(k) {
107
174
  return __awaiter(this, void 0, void 0, function* () {
108
- if (!this._nextSave) {
175
+ if (this._loadedKeys.has(k) || k in this._loadingKeys)
109
176
  return;
177
+ const p = this._getFromStorage(k);
178
+ this._loadingKeys[k] = p;
179
+ const value = yield p;
180
+ delete this._loadingKeys[k];
181
+ this._loadedKeys.add(k);
182
+ if (value) {
183
+ const merged = this._merge(k, value, this.currentValue[k]);
184
+ if (merged) {
185
+ this.currentValue[k] = merged;
186
+ }
110
187
  }
111
- const syncedPromise = new Promise((resolve) => {
112
- this._pendingSaveCbs.push(resolve);
113
- });
114
- yield syncedPromise;
188
+ this.onKeyLoaded && this.onKeyLoaded(k);
115
189
  });
116
190
  }
117
- _writeToStorage() {
118
- this._persister.setItem(this._key, this.serialize(this.currentValue));
119
- for (const cb of this._pendingSaveCbs) {
120
- cb();
191
+ // Returns a promise with a number so that we can wait for flush
192
+ // to finish in the tests. The number is the number of operations
193
+ // it performed, but it's mostly there so that typescript will warn
194
+ // us if we forget to retun the promise from the function.
195
+ _writeToStorage(opts) {
196
+ var _a, _b;
197
+ const promises = [];
198
+ const skipGc = opts === null || opts === void 0 ? void 0 : opts.skipGc;
199
+ if (this._meta.isLoading) {
200
+ // Wait for meta to load and try again, give it a delay so that
201
+ // we don't spend too much time retrying
202
+ const p = new Promise((resolve, reject) => {
203
+ var _a;
204
+ setTimeout(() => this._enqueuePersist(opts
205
+ ? Object.assign(Object.assign({}, opts), { attempts: (opts.attempts || 0) + 1 }) : { attempts: 1 })
206
+ .then(resolve)
207
+ .catch(reject), 10 + ((_a = opts === null || opts === void 0 ? void 0 : opts.attempts) !== null && _a !== void 0 ? _a : 0) * 1000);
208
+ });
209
+ promises.push(p);
210
+ return Promise.all(promises).then((vs) => vs.reduce((acc, x) => acc + x, 0));
211
+ }
212
+ const metaValue = this._meta.value;
213
+ if (!metaValue) {
214
+ // If it's not loading and we don't have the data, then there
215
+ // must be an error and we're not going to be able to save until
216
+ // the error is resolved elsewhere.
217
+ return Promise.resolve(0);
218
+ }
219
+ const keysToDelete = [];
220
+ const keysToUpdate = [];
221
+ for (const k of this._pendingSaveKeys) {
222
+ if (!(k in this.currentValue)) {
223
+ keysToDelete.push(k);
224
+ delete metaValue.objects[k];
225
+ }
226
+ else {
227
+ keysToUpdate.push(k);
228
+ }
121
229
  }
122
- this._pendingSaveCbs.length = 0;
230
+ for (const k of keysToDelete) {
231
+ const p = this._persister.removeItem(k);
232
+ promises.push(p.then(() => 1));
233
+ this._loadedKeys.delete(k);
234
+ this._pendingSaveKeys.delete(k);
235
+ }
236
+ const keysToLoad = [];
237
+ const kvPairs = [[exports.META_KEY, metaValue]];
238
+ const metaObjects = (_a = metaValue.objects) !== null && _a !== void 0 ? _a : {};
239
+ metaValue.objects = metaObjects;
240
+ for (const k of keysToUpdate) {
241
+ if (this._loadedKeys.has(k)) {
242
+ const serializedV = this.serialize(k, this.currentValue[k]);
243
+ kvPairs.push([k, serializedV]);
244
+ const size = this._objectSize(serializedV);
245
+ const m = (_b = metaObjects[k]) !== null && _b !== void 0 ? _b : {
246
+ createdAt: Date.now(),
247
+ updatedAt: Date.now(),
248
+ size,
249
+ };
250
+ m.updatedAt = Date.now();
251
+ m.size = size;
252
+ metaObjects[k] = m;
253
+ this._pendingSaveKeys.delete(k);
254
+ }
255
+ else {
256
+ keysToLoad.push(k);
257
+ }
258
+ }
259
+ const p = this._persister.multiSet(kvPairs);
260
+ promises.push(p.then(() => 1));
261
+ // For the keys that haven't loaded, load the key then try
262
+ // persisting again. We don't want to do any async work here
263
+ // or else we might end up saving older copies of the data to
264
+ // the store.
265
+ for (const k of keysToLoad) {
266
+ const p = this._loadKey(k).then(() => this._enqueuePersist(opts));
267
+ promises.push(p);
268
+ }
269
+ if (!skipGc) {
270
+ this.gc();
271
+ }
272
+ return Promise.all(promises).then((vs) => {
273
+ return vs.reduce((acc, x) => acc + x, 0);
274
+ });
123
275
  }
124
276
  flush() {
125
277
  return __awaiter(this, void 0, void 0, function* () {
@@ -127,36 +279,173 @@ class PersistedObject {
127
279
  return;
128
280
  }
129
281
  clearTimeout(this._nextSave);
130
- this._writeToStorage();
282
+ this._nextSave = null;
283
+ const p = this._writeToStorage();
284
+ return p;
131
285
  });
132
286
  }
133
- _enqueuePersist(cb) {
134
- if (this._nextSave) {
135
- if (cb) {
136
- this._pendingSaveCbs.push(cb);
287
+ _gc() {
288
+ return __awaiter(this, void 0, void 0, function* () {
289
+ if (!this._gcOpts) {
290
+ return;
291
+ }
292
+ const keys = new Set(yield this._persister.getAllKeys());
293
+ keys.delete(exports.META_KEY);
294
+ // Keys we can't delete
295
+ const sacredKeys = new Set(Object.keys(this.currentValue));
296
+ for (const k of Object.keys(this._loadingKeys)) {
297
+ sacredKeys.add(k);
298
+ }
299
+ for (const k of this._loadedKeys) {
300
+ sacredKeys.add(k);
301
+ }
302
+ // Refresh meta from the store so that we're less likely to
303
+ // clobber data from other tabs
304
+ const meta = yield this._refreshMeta();
305
+ if (!meta) {
306
+ this._log.info('Could not gc because we were not able to load meta');
307
+ return;
308
+ }
309
+ const promises = [];
310
+ const deets = {
311
+ gcOpts: this._gcOpts,
312
+ keys,
313
+ sacredKeys,
314
+ removed: [],
315
+ metaRemoved: [],
316
+ removedMissingCount: 0,
317
+ removedOldCount: 0,
318
+ removedThresholdCount: 0,
319
+ removedSizeCount: 0,
320
+ };
321
+ // First, remove all keys we don't know about
322
+ for (const key of keys) {
323
+ if (sacredKeys.has(key) || key in meta.objects) {
324
+ continue;
325
+ }
326
+ this._log.info('Lost track of key in meta', key);
327
+ promises.push(this._persister.removeItem(key));
328
+ deets.removed.push(key);
329
+ deets.removedMissingCount++;
330
+ }
331
+ // Remove anything over the max age
332
+ const now = Date.now();
333
+ for (const [k, m] of Object.entries(meta.objects)) {
334
+ if (!sacredKeys.has(k) &&
335
+ m.updatedAt < now - this._gcOpts.maxAgeMs) {
336
+ promises.push(this._persister.removeItem(k));
337
+ delete meta.objects[k];
338
+ deets.removed.push(k);
339
+ deets.removedOldCount++;
340
+ }
341
+ }
342
+ // Keep queries under max queries
343
+ const maxEntries = Object.entries(meta.objects);
344
+ maxEntries.sort(([_k_a, a_meta], [_k_b, b_meta]) => {
345
+ return a_meta.updatedAt - b_meta.updatedAt;
346
+ });
347
+ const deletableMaxEntries = maxEntries.filter(([x]) => !sacredKeys.has(x));
348
+ if (maxEntries.length > this._gcOpts.maxEntries) {
349
+ for (const [k] of deletableMaxEntries.slice(0, maxEntries.length - this._gcOpts.maxEntries)) {
350
+ promises.push(this._persister.removeItem(k));
351
+ delete meta.objects[k];
352
+ deets.removed.push(k);
353
+ deets.removedThresholdCount++;
354
+ }
137
355
  }
356
+ // Remove oldest entries until we are under max size
357
+ const delEntries = Object.entries(meta.objects);
358
+ delEntries.sort(([_k_a, a_meta], [_k_b, b_meta]) => {
359
+ return a_meta.updatedAt - b_meta.updatedAt;
360
+ });
361
+ const deletableDelEntries = delEntries.filter(([x]) => !sacredKeys.has(x));
362
+ let currentSize = delEntries.reduce((acc, [_k, m]) => {
363
+ return acc + m.size;
364
+ }, 0);
365
+ while (currentSize > 0 &&
366
+ currentSize > this._gcOpts.maxSize &&
367
+ deletableDelEntries.length) {
368
+ const [[k, m]] = deletableDelEntries.splice(0, 1);
369
+ currentSize -= m.size;
370
+ promises.push(this._persister.removeItem(k));
371
+ delete meta.objects[k];
372
+ deets.removed.push(k);
373
+ deets.removedSizeCount++;
374
+ }
375
+ // Update meta to remove keys that are no longer in the store
376
+ for (const k of Object.keys(meta.objects)) {
377
+ if (!keys.has(k) && !sacredKeys.has(k)) {
378
+ delete meta.objects[k];
379
+ }
380
+ }
381
+ if (deets.removed.length || deets.metaRemoved.length) {
382
+ // Trigger a flush of the meta
383
+ promises.push(this._enqueuePersist({ skipGc: true }));
384
+ }
385
+ this._log.info('Completed GC', deets);
386
+ yield Promise.all(promises);
387
+ return deets;
388
+ });
389
+ }
390
+ // Schedules a GC to run in one minute (unless it is already scheduled)
391
+ gc() {
392
+ if (this._nextGc) {
138
393
  return;
139
394
  }
140
- this._nextSave = setTimeout(() => {
395
+ this._nextGc = setTimeout(() => {
141
396
  safeIdleCallback(() => {
142
- this._nextSave = null;
143
- this._writeToStorage();
144
- }, this._idleCallbackMaxWaitMs);
145
- }, this._saveThrottleMs);
397
+ this._nextGc = null;
398
+ this._gc();
399
+ }, 30 * 1000);
400
+ },
401
+ // 1 minute + some jitter to keep multiple tabs from running at same time
402
+ 1000 * 60 + Math.random() * 500);
403
+ }
404
+ _enqueuePersist(opts) {
405
+ return new Promise((resolve, reject) => {
406
+ if (this._nextSave) {
407
+ resolve(0);
408
+ return;
409
+ }
410
+ this._nextSave = setTimeout(() => {
411
+ safeIdleCallback(() => {
412
+ this._nextSave = null;
413
+ this._writeToStorage(opts).then(resolve).catch(reject);
414
+ }, this._idleCallbackMaxWaitMs);
415
+ }, this._saveThrottleMs);
416
+ });
417
+ }
418
+ version() {
419
+ return this._version;
146
420
  }
147
- set(f, cb) {
421
+ // Takes a function that updates the store in place.
422
+ // Uses `mutative` to get a list of keys that were changed
423
+ // so that we know which entries we need to persist to the store.
424
+ updateInPlace(f) {
148
425
  this._version++;
149
- this.currentValue = f(this.currentValue);
150
- if (this._isLoading) {
151
- this._loadedCbs.push(() => this._enqueuePersist(cb));
426
+ const [state, patches] = (0, mutative_1.create)(this.currentValue, f, {
427
+ enablePatches: true,
428
+ });
429
+ for (const patch of patches) {
430
+ const k = patch.path[0];
431
+ if (k && typeof k === 'string') {
432
+ this._pendingSaveKeys.add(k);
433
+ if (!this._loadedKeys.has(k)) {
434
+ this._loadKey(k);
435
+ }
436
+ }
152
437
  }
153
- else {
154
- this._enqueuePersist(cb);
438
+ for (const k of Object.keys(state)) {
439
+ if (!state[k]) {
440
+ debugger;
441
+ }
155
442
  }
156
- for (const sub of this._subs) {
157
- sub(this.currentValue);
443
+ this.currentValue = state;
444
+ this._enqueuePersist();
445
+ for (const cb of this._subs) {
446
+ cb(this.currentValue);
158
447
  }
159
- return this.currentValue;
448
+ return state;
160
449
  }
161
450
  subscribe(cb) {
162
451
  this._subs.push(cb);
@@ -1 +1 @@
1
- {"version":3,"file":"PersistedObject.js","sourceRoot":"","sources":["../../../src/utils/PersistedObject.ts"],"names":[],"mappings":"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","sourcesContent":["// PersistedObjects save data outside of memory.\n//\n// When we load a persisted object, it's possible we call `set`\n// before we finish loading. To address we handle set in two ways:\n//\n// 1. Before load\n// We simply update currentValue in memory\n//\n// 2. After load\n// We update currentValue in memory and in storage\n//\n// Each PersistedObject provides it's own `onMerge`\n// function to handle the merge of data from storage and memory\n// on load\n\n// Uses `requestIdleCallback` if available, otherwise calls the\n// callback immediately\nfunction safeIdleCallback(cb, timeout: number) {\n if (typeof requestIdleCallback === 'undefined') {\n cb();\n } else {\n requestIdleCallback(cb, { timeout });\n }\n}\n\nexport class PersistedObject<T> {\n _subs = [];\n _persister: Storage;\n _key: string;\n _onMerge: (fromStorage: T, inMemoryValue: T) => T | void;\n _loadedCbs: Array<() => void>;\n _isLoading: boolean;\n currentValue: T;\n serialize: (input: T) => any;\n parse: (input: any) => T;\n _saveThrottleMs: number;\n _idleCallbackMaxWaitMs: number;\n _pendingSaveCbs: Array<() => void>;\n _version: number;\n _nextSave: null | NodeJS.Timeout = null;\n\n constructor(\n persister: Storage,\n key: string,\n defaultValue: T,\n /**\n * Merges data from storage with in-memory value on load.\n * If a value is returned from onMerge, that value that will\n * become the current value.\n */\n onMerge: (fromStorage: T, inMemoryValue: T) => T | void,\n serialize = (x: T): any => {\n return x;\n },\n parse = (x: any): T => {\n return x;\n },\n saveThrottleMs = 100,\n idleCallbackMaxWaitMs = 1000,\n ) {\n this._persister = persister;\n this._key = key;\n\n this._onMerge = onMerge;\n\n this._loadedCbs = [];\n this._isLoading = true;\n this.currentValue = defaultValue;\n this.serialize = serialize;\n this.parse = parse;\n this._saveThrottleMs = saveThrottleMs;\n this._pendingSaveCbs = [];\n this._version = 0;\n this._idleCallbackMaxWaitMs = idleCallbackMaxWaitMs;\n\n this._load();\n }\n\n async _getFromStorage() {\n try {\n return this.parse(await this._persister.getItem(this._key));\n } catch (e) {\n console.error(`Unable to read from storage for key=${this._key}`, e);\n return null;\n }\n }\n\n async _load() {\n const fromStorage = await this._getFromStorage();\n this._isLoading = false;\n\n const mergeResult = this._onMerge(fromStorage, this.currentValue);\n if (mergeResult) {\n this.currentValue = mergeResult;\n }\n for (const cb of this._loadedCbs) {\n cb();\n }\n }\n\n async waitForLoaded(): Promise<void> {\n if (!this._isLoading) {\n return;\n }\n const loadedPromise = new Promise<void>((resolve) => {\n this._loadedCbs.push(resolve);\n });\n await loadedPromise;\n }\n\n isLoading() {\n return this._isLoading;\n }\n\n version() {\n return this._version;\n }\n\n async waitForSync() {\n if (!this._nextSave) {\n return;\n }\n const syncedPromise = new Promise<void>((resolve) => {\n this._pendingSaveCbs.push(resolve);\n });\n await syncedPromise;\n }\n\n _writeToStorage() {\n this._persister.setItem(this._key, this.serialize(this.currentValue));\n for (const cb of this._pendingSaveCbs) {\n cb();\n }\n this._pendingSaveCbs.length = 0;\n }\n\n async flush() {\n if (!this._nextSave) {\n return;\n }\n clearTimeout(this._nextSave);\n this._writeToStorage();\n }\n\n _enqueuePersist(cb) {\n if (this._nextSave) {\n if (cb) {\n this._pendingSaveCbs.push(cb);\n }\n return;\n }\n this._nextSave = setTimeout(() => {\n safeIdleCallback(() => {\n this._nextSave = null;\n this._writeToStorage();\n }, this._idleCallbackMaxWaitMs);\n }, this._saveThrottleMs);\n }\n\n set(f: (prev: T) => T, cb?: () => void): T {\n this._version++;\n this.currentValue = f(this.currentValue);\n if (this._isLoading) {\n this._loadedCbs.push(() => this._enqueuePersist(cb));\n } else {\n this._enqueuePersist(cb);\n }\n for (const sub of this._subs) {\n sub(this.currentValue);\n }\n return this.currentValue;\n }\n\n subscribe(cb) {\n this._subs.push(cb);\n cb(this.currentValue);\n\n return () => {\n this._subs = this._subs.filter((x) => x !== cb);\n };\n }\n}\n"]}
1
+ {"version":3,"file":"PersistedObject.js","sourceRoot":"","sources":["../../../src/utils/PersistedObject.ts"],"names":[],"mappings":"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","sourcesContent":["// PersistedObjects save data outside of memory.\n//\n// When we load a persisted object, it's possible we call `set`\n// before we finish loading. To address we handle set in two ways:\n//\n// 1. Before load\n// We simply update currentValue in memory\n//\n// 2. After load\n// We update currentValue in memory and in storage\n//\n// Each PersistedObject provides it's own `onMerge`\n// function to handle the merge of data from storage and memory\n// on load\n\n// Uses `requestIdleCallback` if available, otherwise calls the\n// callback immediately\n\nimport { create } from 'mutative';\nimport type { Logger } from './log.ts';\n\nfunction safeIdleCallback(cb, timeout: number) {\n if (typeof requestIdleCallback === 'undefined') {\n cb();\n } else {\n requestIdleCallback(cb, { timeout });\n }\n}\n\nexport const META_KEY = '__meta';\n\nexport type ObjectMeta = { createdAt: number; updatedAt: number; size: number };\n\nexport type Meta<K extends string> = {\n objects: Record<K, ObjectMeta>;\n};\n\nexport type StorageInterfaceStoreName = 'kv' | 'querySubs' | 'syncSubs';\n\nexport abstract class StorageInterface {\n constructor(appId: string, storeName: StorageInterfaceStoreName) {}\n abstract getItem(key: string): Promise<any>;\n abstract removeItem(key: string): Promise<void>;\n abstract multiSet(keyValuePairs: Array<[string, any]>): Promise<void>;\n abstract getAllKeys(): Promise<string[]>;\n}\n\nexport type GCOpts = {\n maxSize: number;\n maxAgeMs: number;\n maxEntries: number;\n};\n\nexport type Opts<K, T, SerializedT> = {\n persister: StorageInterface;\n /**\n * Merges data from storage with in-memory value on load.\n * The value returned from merge will become the current value.\n */\n merge: (\n key: K,\n fromStorage: T | null | undefined,\n inMemoryValue: T | null | undefined,\n ) => T;\n serialize: (key: K, input: T) => SerializedT;\n parse: (key: K, value: SerializedT) => T;\n objectSize: (x: SerializedT) => number;\n logger: Logger;\n gc: GCOpts | null | undefined;\n saveThrottleMs?: number | null | undefined;\n idleCallbackMaxWaitMs?: number | null | undefined;\n preloadEntryCount?: number | null | undefined;\n};\n\nexport class PersistedObject<K extends string, T, SerializedT> {\n currentValue: Record<K, T>;\n private _subs = [];\n private _persister: StorageInterface;\n private _merge: (key: K, fromStorage: T, inMemoryValue: T) => T;\n private serialize: (key: K, input: T) => SerializedT;\n private parse: (key: K, value: SerializedT) => T;\n private _saveThrottleMs: number;\n private _idleCallbackMaxWaitMs: number;\n private _nextSave: null | NodeJS.Timeout = null;\n private _nextGc: null | NodeJS.Timeout = null;\n private _pendingSaveKeys: Set<K> = new Set();\n private _loadedKeys: Set<K> = new Set();\n private _loadingKeys: Record<K, Promise<T>>;\n private _objectSize: (serializedObject: SerializedT) => number;\n private _log: Logger;\n\n onKeyLoaded: (key: string) => void | null | undefined;\n private _version = 0;\n private _meta: {\n isLoading: boolean;\n onLoadCbs: Array<() => void>;\n value: null | Meta<K>;\n error: null | Error;\n attempts: number;\n loadingPromise?: Promise<Meta<K>> | null | undefined;\n } = {\n isLoading: true,\n onLoadCbs: [],\n value: null,\n error: null,\n attempts: 0,\n };\n private _gcOpts: GCOpts;\n\n constructor(opts: Opts<K, T, SerializedT>) {\n this._persister = opts.persister;\n this._merge = opts.merge;\n this.serialize = opts.serialize;\n this.parse = opts.parse;\n this._objectSize = opts.objectSize;\n this._log = opts.logger;\n this._saveThrottleMs = opts.saveThrottleMs ?? 100;\n this._idleCallbackMaxWaitMs = opts.idleCallbackMaxWaitMs ?? 1000;\n this._gcOpts = opts.gc;\n this.currentValue = {} as Record<K, T>;\n this._loadedKeys = new Set();\n this._loadingKeys = {} as Record<K, Promise<T>>;\n this._initMeta();\n if (opts.preloadEntryCount) {\n this._preloadEntries(opts.preloadEntryCount);\n }\n }\n\n private async _initMeta() {\n if (this._meta.loadingPromise) {\n await this._meta.loadingPromise;\n }\n try {\n const p = this._persister.getItem(META_KEY);\n this._meta.loadingPromise = p;\n const v = await p;\n this._meta.isLoading = false;\n this._meta.error = null;\n this._meta.loadingPromise = null;\n this._meta.attempts = 0;\n const existingObjects = this._meta.value?.objects ?? {};\n const value = v ?? {};\n const objects = value.objects ?? {};\n // Merge the values from storage with in-memory values\n this._meta.value = {\n ...value,\n objects: { ...existingObjects, ...objects },\n } as Meta<K>;\n } catch (e) {\n this._meta.error = e;\n this._meta.attempts++;\n this._meta.loadingPromise = null;\n }\n }\n\n private async _getMeta(): Promise<Meta<K>> {\n if (this._meta.value) {\n return this._meta.value;\n }\n if (this._meta.loadingPromise) {\n await this._meta.loadingPromise;\n return this._meta.value;\n }\n this._initMeta();\n await this._meta.loadingPromise;\n return this._meta.value;\n }\n\n private async _refreshMeta(): Promise<Meta<K>> {\n await this._initMeta();\n return this._meta.value;\n }\n\n private async _preloadEntries(n: number) {\n const meta = await this.waitForMetaToLoad();\n const entries = Object.entries(meta.objects) as Array<[K, ObjectMeta]>;\n entries.sort(([_k_a, a_meta], [_k_b, b_meta]) => {\n return b_meta.updatedAt - a_meta.updatedAt;\n });\n for (const [k] of entries.slice(0, n)) {\n this._loadKey(k);\n }\n }\n\n private async _getFromStorage(key: K) {\n try {\n const data = await this._persister.getItem(key);\n if (!data) {\n return data;\n }\n const parsed = this.parse(key, data as SerializedT);\n return parsed;\n } catch (e) {\n console.error(`Unable to read from storage for key=${key}`, e);\n return null;\n }\n }\n\n public async waitForKeyToLoad(k: K) {\n if (this._loadedKeys.has(k)) {\n return this.currentValue[k];\n }\n await (this._loadingKeys[k] || this._loadKey(k));\n return this.currentValue[k];\n }\n\n // Used for tests\n public async waitForMetaToLoad() {\n return this._getMeta();\n }\n\n // Unloads the key so that it can be garbage collected, but does not\n // delete it. Removes the key from currentValue.\n public unloadKey(k: K) {\n this._loadedKeys.delete(k);\n delete this._loadingKeys[k];\n delete this.currentValue[k];\n }\n\n private async _loadKey(k: K) {\n if (this._loadedKeys.has(k) || k in this._loadingKeys) return;\n const p = this._getFromStorage(k);\n this._loadingKeys[k] = p;\n const value = await p;\n delete this._loadingKeys[k];\n this._loadedKeys.add(k);\n\n if (value) {\n const merged = this._merge(k, value, this.currentValue[k]);\n if (merged) {\n this.currentValue[k] = merged;\n }\n }\n this.onKeyLoaded && this.onKeyLoaded(k);\n }\n\n // Returns a promise with a number so that we can wait for flush\n // to finish in the tests. The number is the number of operations\n // it performed, but it's mostly there so that typescript will warn\n // us if we forget to retun the promise from the function.\n private _writeToStorage(opts?: {\n skipGc?: boolean | null | undefined;\n attempts?: number | null | undefined;\n }): Promise<number> {\n const promises: Promise<number>[] = [];\n const skipGc = opts?.skipGc;\n if (this._meta.isLoading) {\n // Wait for meta to load and try again, give it a delay so that\n // we don't spend too much time retrying\n const p: Promise<number> = new Promise((resolve, reject) => {\n setTimeout(\n () =>\n this._enqueuePersist(\n opts\n ? { ...opts, attempts: (opts.attempts || 0) + 1 }\n : { attempts: 1 },\n )\n .then(resolve)\n .catch(reject),\n 10 + (opts?.attempts ?? 0) * 1000,\n );\n });\n promises.push(p);\n return Promise.all(promises).then((vs) =>\n vs.reduce((acc, x) => acc + x, 0),\n );\n }\n const metaValue = this._meta.value;\n if (!metaValue) {\n // If it's not loading and we don't have the data, then there\n // must be an error and we're not going to be able to save until\n // the error is resolved elsewhere.\n return Promise.resolve(0);\n }\n const keysToDelete = [];\n const keysToUpdate = [];\n for (const k of this._pendingSaveKeys) {\n if (!(k in this.currentValue)) {\n keysToDelete.push(k);\n delete metaValue.objects[k];\n } else {\n keysToUpdate.push(k);\n }\n }\n\n for (const k of keysToDelete) {\n const p = this._persister.removeItem(k);\n promises.push(p.then(() => 1));\n this._loadedKeys.delete(k);\n this._pendingSaveKeys.delete(k);\n }\n\n const keysToLoad = [];\n\n const kvPairs: Array<[string, any]> = [[META_KEY, metaValue]];\n const metaObjects: Meta<K>['objects'] =\n metaValue.objects ?? ({} as Meta<K>['objects']);\n metaValue.objects = metaObjects;\n for (const k of keysToUpdate) {\n if (this._loadedKeys.has(k)) {\n const serializedV = this.serialize(k, this.currentValue[k]);\n kvPairs.push([k, serializedV]);\n const size = this._objectSize(serializedV);\n const m = metaObjects[k] ?? {\n createdAt: Date.now(),\n updatedAt: Date.now(),\n size,\n };\n m.updatedAt = Date.now();\n m.size = size;\n metaObjects[k] = m;\n this._pendingSaveKeys.delete(k);\n } else {\n keysToLoad.push(k);\n }\n }\n\n const p = this._persister.multiSet(kvPairs);\n promises.push(p.then(() => 1));\n\n // For the keys that haven't loaded, load the key then try\n // persisting again. We don't want to do any async work here\n // or else we might end up saving older copies of the data to\n // the store.\n for (const k of keysToLoad) {\n const p = this._loadKey(k).then(() => this._enqueuePersist(opts));\n promises.push(p);\n }\n\n if (!skipGc) {\n this.gc();\n }\n\n return Promise.all(promises).then((vs) => {\n return vs.reduce((acc, x) => acc + x, 0);\n });\n }\n\n async flush() {\n if (!this._nextSave) {\n return;\n }\n clearTimeout(this._nextSave);\n this._nextSave = null;\n const p = this._writeToStorage();\n return p;\n }\n\n private async _gc() {\n if (!this._gcOpts) {\n return;\n }\n const keys = new Set(await this._persister.getAllKeys());\n keys.delete(META_KEY);\n\n // Keys we can't delete\n const sacredKeys = new Set(Object.keys(this.currentValue));\n for (const k of Object.keys(this._loadingKeys)) {\n sacredKeys.add(k);\n }\n for (const k of this._loadedKeys) {\n sacredKeys.add(k);\n }\n\n // Refresh meta from the store so that we're less likely to\n // clobber data from other tabs\n const meta = await this._refreshMeta();\n if (!meta) {\n this._log.info('Could not gc because we were not able to load meta');\n return;\n }\n\n const promises = [];\n\n const deets = {\n gcOpts: this._gcOpts,\n keys,\n sacredKeys,\n removed: [],\n metaRemoved: [],\n removedMissingCount: 0,\n removedOldCount: 0,\n removedThresholdCount: 0,\n removedSizeCount: 0,\n };\n\n // First, remove all keys we don't know about\n for (const key of keys) {\n if (sacredKeys.has(key) || key in meta.objects) {\n continue;\n }\n this._log.info('Lost track of key in meta', key);\n promises.push(this._persister.removeItem(key));\n deets.removed.push(key);\n deets.removedMissingCount++;\n }\n\n // Remove anything over the max age\n const now = Date.now();\n for (const [k, m] of Object.entries(meta.objects)) {\n if (\n !sacredKeys.has(k) &&\n (m as ObjectMeta).updatedAt < now - this._gcOpts.maxAgeMs\n ) {\n promises.push(this._persister.removeItem(k));\n delete meta.objects[k];\n deets.removed.push(k);\n deets.removedOldCount++;\n }\n }\n\n // Keep queries under max queries\n const maxEntries = Object.entries(meta.objects) as Array<[K, ObjectMeta]>;\n maxEntries.sort(([_k_a, a_meta], [_k_b, b_meta]) => {\n return a_meta.updatedAt - b_meta.updatedAt;\n });\n\n const deletableMaxEntries = maxEntries.filter(([x]) => !sacredKeys.has(x));\n if (maxEntries.length > this._gcOpts.maxEntries) {\n for (const [k] of deletableMaxEntries.slice(\n 0,\n maxEntries.length - this._gcOpts.maxEntries,\n )) {\n promises.push(this._persister.removeItem(k));\n delete meta.objects[k];\n deets.removed.push(k);\n deets.removedThresholdCount++;\n }\n }\n\n // Remove oldest entries until we are under max size\n const delEntries = Object.entries(meta.objects) as Array<[K, ObjectMeta]>;\n delEntries.sort(([_k_a, a_meta], [_k_b, b_meta]) => {\n return a_meta.updatedAt - b_meta.updatedAt;\n });\n const deletableDelEntries = delEntries.filter(([x]) => !sacredKeys.has(x));\n\n let currentSize = delEntries.reduce((acc, [_k, m]) => {\n return acc + m.size;\n }, 0);\n\n while (\n currentSize > 0 &&\n currentSize > this._gcOpts.maxSize &&\n deletableDelEntries.length\n ) {\n const [[k, m]] = deletableDelEntries.splice(0, 1);\n currentSize -= m.size;\n promises.push(this._persister.removeItem(k));\n delete meta.objects[k];\n deets.removed.push(k);\n deets.removedSizeCount++;\n }\n\n // Update meta to remove keys that are no longer in the store\n for (const k of Object.keys(meta.objects)) {\n if (!keys.has(k) && !sacredKeys.has(k)) {\n delete meta.objects[k];\n }\n }\n\n if (deets.removed.length || deets.metaRemoved.length) {\n // Trigger a flush of the meta\n promises.push(this._enqueuePersist({ skipGc: true }));\n }\n\n this._log.info('Completed GC', deets);\n\n await Promise.all(promises);\n return deets;\n }\n\n // Schedules a GC to run in one minute (unless it is already scheduled)\n gc() {\n if (this._nextGc) {\n return;\n }\n this._nextGc = setTimeout(\n () => {\n safeIdleCallback(() => {\n this._nextGc = null;\n this._gc();\n }, 30 * 1000);\n },\n // 1 minute + some jitter to keep multiple tabs from running at same time\n 1000 * 60 + Math.random() * 500,\n );\n }\n\n private _enqueuePersist(opts?: {\n skipGc?: boolean | null | undefined;\n attempts?: number | null | undefined;\n }): Promise<number> {\n return new Promise((resolve, reject) => {\n if (this._nextSave) {\n resolve(0);\n return;\n }\n\n this._nextSave = setTimeout(() => {\n safeIdleCallback(() => {\n this._nextSave = null;\n this._writeToStorage(opts).then(resolve).catch(reject);\n }, this._idleCallbackMaxWaitMs);\n }, this._saveThrottleMs);\n });\n }\n\n version() {\n return this._version;\n }\n\n // Takes a function that updates the store in place.\n // Uses `mutative` to get a list of keys that were changed\n // so that we know which entries we need to persist to the store.\n public updateInPlace(f: (prev: Record<string, T>) => void) {\n this._version++;\n const [state, patches] = create(this.currentValue, f, {\n enablePatches: true,\n });\n for (const patch of patches) {\n const k = patch.path[0];\n if (k && typeof k === 'string') {\n this._pendingSaveKeys.add(k as K);\n if (!this._loadedKeys.has(k as K)) {\n this._loadKey(k as K);\n }\n }\n }\n\n for (const k of Object.keys(state)) {\n if (!state[k]) {\n debugger;\n }\n }\n\n this.currentValue = state;\n this._enqueuePersist();\n for (const cb of this._subs) {\n cb(this.currentValue);\n }\n return state;\n }\n\n public subscribe(cb: (value: Record<K, T>) => void) {\n this._subs.push(cb);\n cb(this.currentValue);\n\n return () => {\n this._subs = this._subs.filter((x) => x !== cb);\n };\n }\n}\n"]}
@@ -0,0 +1,11 @@
1
+ import { StorageInterface, StorageInterfaceStoreName } from './utils/PersistedObject.js';
2
+ export default class InMemoryStorage extends StorageInterface {
3
+ private store;
4
+ constructor(appId: string, dbName: StorageInterfaceStoreName);
5
+ getItem(k: any): Promise<any>;
6
+ setItem(k: any, v: any): Promise<void>;
7
+ getAllKeys(): Promise<string[]>;
8
+ multiSet(keyValuePairs: Array<[string, any]>): Promise<void>;
9
+ removeItem(key: string): Promise<void>;
10
+ }
11
+ //# sourceMappingURL=InMemoryStorage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InMemoryStorage.d.ts","sourceRoot":"","sources":["../../src/InMemoryStorage.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,yBAAyB,EAC1B,MAAM,4BAA4B,CAAC;AAEpC,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,gBAAgB;IAC3D,OAAO,CAAC,KAAK,CAAmB;gBACpB,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,yBAAyB;IAKtD,OAAO,CAAC,CAAC,KAAA;IAIT,OAAO,CAAC,CAAC,KAAA,EAAE,CAAC,KAAA;IAIZ,UAAU,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAI/B,QAAQ,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAM5D,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG7C"}