@instantdb/core 0.22.96-experimental.drewh-ts-target.20759870126.1 → 0.22.96-experimental.surgical.20765334274.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/dist/commonjs/Connection.js +51 -50
- package/dist/commonjs/Connection.js.map +1 -1
- package/dist/commonjs/InMemoryStorage.js +32 -13
- package/dist/commonjs/InMemoryStorage.js.map +1 -1
- package/dist/commonjs/IndexedDBStorage.js +217 -193
- package/dist/commonjs/IndexedDBStorage.js.map +1 -1
- package/dist/commonjs/InstantError.js +0 -1
- package/dist/commonjs/InstantError.js.map +1 -1
- package/dist/commonjs/Reactor.js +610 -566
- package/dist/commonjs/Reactor.js.map +1 -1
- package/dist/commonjs/StorageAPI.js +70 -51
- package/dist/commonjs/StorageAPI.js.map +1 -1
- package/dist/commonjs/SyncTable.js +81 -68
- package/dist/commonjs/SyncTable.js.map +1 -1
- package/dist/commonjs/WindowNetworkListener.js +13 -2
- package/dist/commonjs/WindowNetworkListener.js.map +1 -1
- package/dist/commonjs/__types__/fieldsTypeTest.js +16 -8
- package/dist/commonjs/__types__/fieldsTypeTest.js.map +1 -1
- package/dist/commonjs/__types__/useDatesTypeTest.js +6 -3
- package/dist/commonjs/__types__/useDatesTypeTest.js.map +1 -1
- package/dist/commonjs/authAPI.js +79 -62
- package/dist/commonjs/authAPI.js.map +1 -1
- package/dist/commonjs/createRouteHandler.js +15 -5
- package/dist/commonjs/createRouteHandler.js.map +1 -1
- package/dist/commonjs/datalog.js +1 -1
- package/dist/commonjs/datalog.js.map +1 -1
- package/dist/commonjs/devtool.js +8 -26
- package/dist/commonjs/devtool.js.map +1 -1
- package/dist/commonjs/framework.d.ts.map +1 -1
- package/dist/commonjs/framework.js +152 -142
- package/dist/commonjs/framework.js.map +1 -1
- package/dist/commonjs/index.js +190 -204
- package/dist/commonjs/index.js.map +1 -1
- package/dist/commonjs/instaml.js +30 -44
- package/dist/commonjs/instaml.js.map +1 -1
- package/dist/commonjs/instaql.js +33 -25
- package/dist/commonjs/instaql.js.map +1 -1
- package/dist/commonjs/parseSchemaFromJSON.js +7 -6
- package/dist/commonjs/parseSchemaFromJSON.js.map +1 -1
- package/dist/commonjs/presence.js +8 -7
- package/dist/commonjs/presence.js.map +1 -1
- package/dist/commonjs/queryValidation.js +2 -1
- package/dist/commonjs/queryValidation.js.map +1 -1
- package/dist/commonjs/schema.js +6 -8
- package/dist/commonjs/schema.js.map +1 -1
- package/dist/commonjs/schemaTypes.js +3 -22
- package/dist/commonjs/schemaTypes.js.map +1 -1
- package/dist/commonjs/store.js +38 -29
- package/dist/commonjs/store.js.map +1 -1
- package/dist/commonjs/transactionValidation.js +2 -1
- package/dist/commonjs/transactionValidation.js.map +1 -1
- package/dist/commonjs/utils/Deferred.js +0 -3
- package/dist/commonjs/utils/Deferred.js.map +1 -1
- package/dist/commonjs/utils/PersistedObject.js +233 -216
- package/dist/commonjs/utils/PersistedObject.js.map +1 -1
- package/dist/commonjs/utils/fetch.js +19 -9
- package/dist/commonjs/utils/fetch.js.map +1 -1
- package/dist/commonjs/utils/linkIndex.js +4 -2
- package/dist/commonjs/utils/linkIndex.js.map +1 -1
- package/dist/commonjs/utils/object.js +1 -1
- package/dist/commonjs/utils/object.js.map +1 -1
- package/dist/esm/Connection.js +51 -50
- package/dist/esm/Connection.js.map +1 -1
- package/dist/esm/InMemoryStorage.js +32 -13
- package/dist/esm/InMemoryStorage.js.map +1 -1
- package/dist/esm/IndexedDBStorage.js +217 -193
- package/dist/esm/IndexedDBStorage.js.map +1 -1
- package/dist/esm/InstantError.js +0 -1
- package/dist/esm/InstantError.js.map +1 -1
- package/dist/esm/Reactor.js +610 -566
- package/dist/esm/Reactor.js.map +1 -1
- package/dist/esm/StorageAPI.js +70 -51
- package/dist/esm/StorageAPI.js.map +1 -1
- package/dist/esm/SyncTable.js +81 -68
- package/dist/esm/SyncTable.js.map +1 -1
- package/dist/esm/WindowNetworkListener.js +13 -2
- package/dist/esm/WindowNetworkListener.js.map +1 -1
- package/dist/esm/__types__/fieldsTypeTest.js +16 -8
- package/dist/esm/__types__/fieldsTypeTest.js.map +1 -1
- package/dist/esm/__types__/useDatesTypeTest.js +6 -3
- package/dist/esm/__types__/useDatesTypeTest.js.map +1 -1
- package/dist/esm/authAPI.js +79 -62
- package/dist/esm/authAPI.js.map +1 -1
- package/dist/esm/createRouteHandler.js +15 -5
- package/dist/esm/createRouteHandler.js.map +1 -1
- package/dist/esm/datalog.js +1 -1
- package/dist/esm/datalog.js.map +1 -1
- package/dist/esm/devtool.js +8 -26
- package/dist/esm/devtool.js.map +1 -1
- package/dist/esm/framework.d.ts.map +1 -1
- package/dist/esm/framework.js +152 -142
- package/dist/esm/framework.js.map +1 -1
- package/dist/esm/index.js +190 -204
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/instaml.js +30 -44
- package/dist/esm/instaml.js.map +1 -1
- package/dist/esm/instaql.js +33 -25
- package/dist/esm/instaql.js.map +1 -1
- package/dist/esm/parseSchemaFromJSON.js +7 -6
- package/dist/esm/parseSchemaFromJSON.js.map +1 -1
- package/dist/esm/presence.js +8 -7
- package/dist/esm/presence.js.map +1 -1
- package/dist/esm/queryValidation.js +2 -1
- package/dist/esm/queryValidation.js.map +1 -1
- package/dist/esm/schema.js +6 -8
- package/dist/esm/schema.js.map +1 -1
- package/dist/esm/schemaTypes.js +3 -22
- package/dist/esm/schemaTypes.js.map +1 -1
- package/dist/esm/store.js +38 -29
- package/dist/esm/store.js.map +1 -1
- package/dist/esm/transactionValidation.js +2 -1
- package/dist/esm/transactionValidation.js.map +1 -1
- package/dist/esm/utils/Deferred.js +0 -3
- package/dist/esm/utils/Deferred.js.map +1 -1
- package/dist/esm/utils/PersistedObject.js +233 -216
- package/dist/esm/utils/PersistedObject.js.map +1 -1
- package/dist/esm/utils/fetch.js +19 -9
- package/dist/esm/utils/fetch.js.map +1 -1
- package/dist/esm/utils/linkIndex.js +4 -2
- package/dist/esm/utils/linkIndex.js.map +1 -1
- package/dist/esm/utils/object.js +1 -1
- package/dist/esm/utils/object.js.map +1 -1
- package/dist/standalone/index.js +2367 -2610
- package/dist/standalone/index.umd.cjs +3 -3
- package/package.json +2 -2
- package/src/framework.ts +1 -0
|
@@ -12,6 +12,15 @@
|
|
|
12
12
|
// Each PersistedObject provides it's own `onMerge`
|
|
13
13
|
// function to handle the merge of data from storage and memory
|
|
14
14
|
// on load
|
|
15
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
16
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
17
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
18
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
19
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
20
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
21
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
22
|
+
});
|
|
23
|
+
};
|
|
15
24
|
// Uses `requestIdleCallback` if available, otherwise calls the
|
|
16
25
|
// callback immediately
|
|
17
26
|
import { create } from 'mutative';
|
|
@@ -28,40 +37,29 @@ export class StorageInterface {
|
|
|
28
37
|
constructor(appId, storeName) { }
|
|
29
38
|
}
|
|
30
39
|
export class PersistedObject {
|
|
31
|
-
currentValue;
|
|
32
|
-
_subs = [];
|
|
33
|
-
_persister;
|
|
34
|
-
_merge;
|
|
35
|
-
serialize;
|
|
36
|
-
parse;
|
|
37
|
-
_saveThrottleMs;
|
|
38
|
-
_idleCallbackMaxWaitMs;
|
|
39
|
-
_nextSave = null;
|
|
40
|
-
_nextGc = null;
|
|
41
|
-
_pendingSaveKeys = new Set();
|
|
42
|
-
_loadedKeys = new Set();
|
|
43
|
-
_loadingKeys;
|
|
44
|
-
_objectSize;
|
|
45
|
-
_log;
|
|
46
|
-
onKeyLoaded;
|
|
47
|
-
_version = 0;
|
|
48
|
-
_meta = {
|
|
49
|
-
isLoading: true,
|
|
50
|
-
onLoadCbs: [],
|
|
51
|
-
value: null,
|
|
52
|
-
error: null,
|
|
53
|
-
attempts: 0,
|
|
54
|
-
};
|
|
55
|
-
_gcOpts;
|
|
56
40
|
constructor(opts) {
|
|
41
|
+
var _a, _b;
|
|
42
|
+
this._subs = [];
|
|
43
|
+
this._nextSave = null;
|
|
44
|
+
this._nextGc = null;
|
|
45
|
+
this._pendingSaveKeys = new Set();
|
|
46
|
+
this._loadedKeys = new Set();
|
|
47
|
+
this._version = 0;
|
|
48
|
+
this._meta = {
|
|
49
|
+
isLoading: true,
|
|
50
|
+
onLoadCbs: [],
|
|
51
|
+
value: null,
|
|
52
|
+
error: null,
|
|
53
|
+
attempts: 0,
|
|
54
|
+
};
|
|
57
55
|
this._persister = opts.persister;
|
|
58
56
|
this._merge = opts.merge;
|
|
59
57
|
this.serialize = opts.serialize;
|
|
60
58
|
this.parse = opts.parse;
|
|
61
59
|
this._objectSize = opts.objectSize;
|
|
62
60
|
this._log = opts.logger;
|
|
63
|
-
this._saveThrottleMs = opts.saveThrottleMs
|
|
64
|
-
this._idleCallbackMaxWaitMs = opts.idleCallbackMaxWaitMs
|
|
61
|
+
this._saveThrottleMs = (_a = opts.saveThrottleMs) !== null && _a !== void 0 ? _a : 100;
|
|
62
|
+
this._idleCallbackMaxWaitMs = (_b = opts.idleCallbackMaxWaitMs) !== null && _b !== void 0 ? _b : 1000;
|
|
65
63
|
this._gcOpts = opts.gc;
|
|
66
64
|
this.currentValue = {};
|
|
67
65
|
this._loadedKeys = new Set();
|
|
@@ -71,85 +69,97 @@ export class PersistedObject {
|
|
|
71
69
|
this._preloadEntries(opts.preloadEntryCount);
|
|
72
70
|
}
|
|
73
71
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
objects: {
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
72
|
+
_initMeta() {
|
|
73
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
74
|
+
var _a, _b, _c;
|
|
75
|
+
if (this._meta.loadingPromise) {
|
|
76
|
+
yield this._meta.loadingPromise;
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
const p = this._persister.getItem(META_KEY);
|
|
80
|
+
this._meta.loadingPromise = p;
|
|
81
|
+
const v = yield p;
|
|
82
|
+
this._meta.isLoading = false;
|
|
83
|
+
this._meta.error = null;
|
|
84
|
+
this._meta.loadingPromise = null;
|
|
85
|
+
this._meta.attempts = 0;
|
|
86
|
+
const existingObjects = (_b = (_a = this._meta.value) === null || _a === void 0 ? void 0 : _a.objects) !== null && _b !== void 0 ? _b : {};
|
|
87
|
+
const value = v !== null && v !== void 0 ? v : {};
|
|
88
|
+
const objects = (_c = value.objects) !== null && _c !== void 0 ? _c : {};
|
|
89
|
+
// Merge the values from storage with in-memory values
|
|
90
|
+
this._meta.value = Object.assign(Object.assign({}, value), { objects: Object.assign(Object.assign({}, existingObjects), objects) });
|
|
91
|
+
}
|
|
92
|
+
catch (e) {
|
|
93
|
+
this._meta.error = e;
|
|
94
|
+
this._meta.attempts++;
|
|
95
|
+
this._meta.loadingPromise = null;
|
|
96
|
+
}
|
|
97
|
+
});
|
|
100
98
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
99
|
+
_getMeta() {
|
|
100
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
101
|
+
if (this._meta.value) {
|
|
102
|
+
return this._meta.value;
|
|
103
|
+
}
|
|
104
|
+
if (this._meta.loadingPromise) {
|
|
105
|
+
yield this._meta.loadingPromise;
|
|
106
|
+
return this._meta.value;
|
|
107
|
+
}
|
|
108
|
+
this._initMeta();
|
|
109
|
+
yield this._meta.loadingPromise;
|
|
107
110
|
return this._meta.value;
|
|
108
|
-
}
|
|
109
|
-
this._initMeta();
|
|
110
|
-
await this._meta.loadingPromise;
|
|
111
|
-
return this._meta.value;
|
|
111
|
+
});
|
|
112
112
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
113
|
+
_refreshMeta() {
|
|
114
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
115
|
+
yield this._initMeta();
|
|
116
|
+
return this._meta.value;
|
|
117
|
+
});
|
|
116
118
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
119
|
+
_preloadEntries(n) {
|
|
120
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
121
|
+
const meta = yield this.waitForMetaToLoad();
|
|
122
|
+
if (!meta)
|
|
123
|
+
return;
|
|
124
|
+
const entries = Object.entries(meta.objects);
|
|
125
|
+
entries.sort(([_k_a, a_meta], [_k_b, b_meta]) => {
|
|
126
|
+
return b_meta.updatedAt - a_meta.updatedAt;
|
|
127
|
+
});
|
|
128
|
+
for (const [k] of entries.slice(0, n)) {
|
|
129
|
+
this._loadKey(k);
|
|
130
|
+
}
|
|
124
131
|
});
|
|
125
|
-
for (const [k] of entries.slice(0, n)) {
|
|
126
|
-
this._loadKey(k);
|
|
127
|
-
}
|
|
128
132
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
133
|
+
_getFromStorage(key) {
|
|
134
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
135
|
+
try {
|
|
136
|
+
const data = yield this._persister.getItem(key);
|
|
137
|
+
if (!data) {
|
|
138
|
+
return data;
|
|
139
|
+
}
|
|
140
|
+
const parsed = this.parse(key, data);
|
|
141
|
+
return parsed;
|
|
134
142
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
return null;
|
|
141
|
-
}
|
|
143
|
+
catch (e) {
|
|
144
|
+
console.error(`Unable to read from storage for key=${key}`, e);
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
});
|
|
142
148
|
}
|
|
143
|
-
|
|
144
|
-
|
|
149
|
+
waitForKeyToLoad(k) {
|
|
150
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
151
|
+
if (this._loadedKeys.has(k)) {
|
|
152
|
+
return this.currentValue[k];
|
|
153
|
+
}
|
|
154
|
+
yield (this._loadingKeys[k] || this._loadKey(k));
|
|
145
155
|
return this.currentValue[k];
|
|
146
|
-
}
|
|
147
|
-
await (this._loadingKeys[k] || this._loadKey(k));
|
|
148
|
-
return this.currentValue[k];
|
|
156
|
+
});
|
|
149
157
|
}
|
|
150
158
|
// Used for tests
|
|
151
|
-
|
|
152
|
-
return this
|
|
159
|
+
waitForMetaToLoad() {
|
|
160
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
161
|
+
return this._getMeta();
|
|
162
|
+
});
|
|
153
163
|
}
|
|
154
164
|
// Unloads the key so that it can be garbage collected, but does not
|
|
155
165
|
// delete it. Removes the key from currentValue.
|
|
@@ -158,38 +168,41 @@ export class PersistedObject {
|
|
|
158
168
|
delete this._loadingKeys[k];
|
|
159
169
|
delete this.currentValue[k];
|
|
160
170
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
171
|
+
_loadKey(k) {
|
|
172
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
173
|
+
if (this._loadedKeys.has(k) || k in this._loadingKeys)
|
|
174
|
+
return;
|
|
175
|
+
const p = this._getFromStorage(k);
|
|
176
|
+
this._loadingKeys[k] = p;
|
|
177
|
+
const value = yield p;
|
|
178
|
+
delete this._loadingKeys[k];
|
|
179
|
+
this._loadedKeys.add(k);
|
|
180
|
+
if (value) {
|
|
181
|
+
const merged = this._merge(k, value, this.currentValue[k]);
|
|
182
|
+
if (merged) {
|
|
183
|
+
this.currentValue[k] = merged;
|
|
184
|
+
}
|
|
173
185
|
}
|
|
174
|
-
|
|
175
|
-
|
|
186
|
+
this.onKeyLoaded && this.onKeyLoaded(k);
|
|
187
|
+
});
|
|
176
188
|
}
|
|
177
189
|
// Returns a promise with a number so that we can wait for flush
|
|
178
190
|
// to finish in the tests. The number is the number of operations
|
|
179
191
|
// it performed, but it's mostly there so that typescript will warn
|
|
180
192
|
// us if we forget to retun the promise from the function.
|
|
181
193
|
_writeToStorage(opts) {
|
|
194
|
+
var _a, _b;
|
|
182
195
|
const promises = [];
|
|
183
|
-
const skipGc = opts
|
|
196
|
+
const skipGc = opts === null || opts === void 0 ? void 0 : opts.skipGc;
|
|
184
197
|
if (this._meta.isLoading) {
|
|
185
198
|
// Wait for meta to load and try again, give it a delay so that
|
|
186
199
|
// we don't spend too much time retrying
|
|
187
200
|
const p = new Promise((resolve, reject) => {
|
|
201
|
+
var _a;
|
|
188
202
|
setTimeout(() => this._enqueuePersist(opts
|
|
189
|
-
? {
|
|
190
|
-
: { attempts: 1 })
|
|
203
|
+
? Object.assign(Object.assign({}, opts), { attempts: (opts.attempts || 0) + 1 }) : { attempts: 1 })
|
|
191
204
|
.then(resolve)
|
|
192
|
-
.catch(reject), 10 + (opts
|
|
205
|
+
.catch(reject), 10 + ((_a = opts === null || opts === void 0 ? void 0 : opts.attempts) !== null && _a !== void 0 ? _a : 0) * 1000);
|
|
193
206
|
});
|
|
194
207
|
promises.push(p);
|
|
195
208
|
return Promise.all(promises).then((vs) => vs.reduce((acc, x) => acc + x, 0));
|
|
@@ -220,14 +233,14 @@ export class PersistedObject {
|
|
|
220
233
|
}
|
|
221
234
|
const keysToLoad = [];
|
|
222
235
|
const kvPairs = [[META_KEY, metaValue]];
|
|
223
|
-
const metaObjects = metaValue.objects
|
|
236
|
+
const metaObjects = (_a = metaValue.objects) !== null && _a !== void 0 ? _a : {};
|
|
224
237
|
metaValue.objects = metaObjects;
|
|
225
238
|
for (const k of keysToUpdate) {
|
|
226
239
|
if (this._loadedKeys.has(k)) {
|
|
227
240
|
const serializedV = this.serialize(k, this.currentValue[k]);
|
|
228
241
|
kvPairs.push([k, serializedV]);
|
|
229
242
|
const size = this._objectSize(serializedV);
|
|
230
|
-
const m = metaObjects[k]
|
|
243
|
+
const m = (_b = metaObjects[k]) !== null && _b !== void 0 ? _b : {
|
|
231
244
|
createdAt: Date.now(),
|
|
232
245
|
updatedAt: Date.now(),
|
|
233
246
|
size,
|
|
@@ -258,115 +271,119 @@ export class PersistedObject {
|
|
|
258
271
|
return vs.reduce((acc, x) => acc + x, 0);
|
|
259
272
|
});
|
|
260
273
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
274
|
+
flush() {
|
|
275
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
276
|
+
if (!this._nextSave) {
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
clearTimeout(this._nextSave);
|
|
280
|
+
this._nextSave = null;
|
|
281
|
+
const p = this._writeToStorage();
|
|
282
|
+
return p;
|
|
283
|
+
});
|
|
269
284
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
const keys = new Set(await this._persister.getAllKeys());
|
|
275
|
-
keys.delete(META_KEY);
|
|
276
|
-
// Keys we can't delete
|
|
277
|
-
const sacredKeys = new Set(Object.keys(this.currentValue));
|
|
278
|
-
for (const k of Object.keys(this._loadingKeys)) {
|
|
279
|
-
sacredKeys.add(k);
|
|
280
|
-
}
|
|
281
|
-
for (const k of this._loadedKeys) {
|
|
282
|
-
sacredKeys.add(k);
|
|
283
|
-
}
|
|
284
|
-
// Refresh meta from the store so that we're less likely to
|
|
285
|
-
// clobber data from other tabs
|
|
286
|
-
const meta = await this._refreshMeta();
|
|
287
|
-
if (!meta) {
|
|
288
|
-
this._log.info('Could not gc because we were not able to load meta');
|
|
289
|
-
return;
|
|
290
|
-
}
|
|
291
|
-
const promises = [];
|
|
292
|
-
const deets = {
|
|
293
|
-
gcOpts: this._gcOpts,
|
|
294
|
-
keys,
|
|
295
|
-
sacredKeys,
|
|
296
|
-
removed: [],
|
|
297
|
-
metaRemoved: [],
|
|
298
|
-
removedMissingCount: 0,
|
|
299
|
-
removedOldCount: 0,
|
|
300
|
-
removedThresholdCount: 0,
|
|
301
|
-
removedSizeCount: 0,
|
|
302
|
-
};
|
|
303
|
-
// First, remove all keys we don't know about
|
|
304
|
-
for (const key of keys) {
|
|
305
|
-
if (sacredKeys.has(key) || key in meta.objects) {
|
|
306
|
-
continue;
|
|
285
|
+
_gc() {
|
|
286
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
287
|
+
if (!this._gcOpts) {
|
|
288
|
+
return;
|
|
307
289
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
const now = Date.now();
|
|
315
|
-
for (const [k, m] of Object.entries(meta.objects)) {
|
|
316
|
-
if (!sacredKeys.has(k) &&
|
|
317
|
-
m.updatedAt < now - this._gcOpts.maxAgeMs) {
|
|
318
|
-
promises.push(this._persister.removeItem(k));
|
|
319
|
-
delete meta.objects[k];
|
|
320
|
-
deets.removed.push(k);
|
|
321
|
-
deets.removedOldCount++;
|
|
290
|
+
const keys = new Set(yield this._persister.getAllKeys());
|
|
291
|
+
keys.delete(META_KEY);
|
|
292
|
+
// Keys we can't delete
|
|
293
|
+
const sacredKeys = new Set(Object.keys(this.currentValue));
|
|
294
|
+
for (const k of Object.keys(this._loadingKeys)) {
|
|
295
|
+
sacredKeys.add(k);
|
|
322
296
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
297
|
+
for (const k of this._loadedKeys) {
|
|
298
|
+
sacredKeys.add(k);
|
|
299
|
+
}
|
|
300
|
+
// Refresh meta from the store so that we're less likely to
|
|
301
|
+
// clobber data from other tabs
|
|
302
|
+
const meta = yield this._refreshMeta();
|
|
303
|
+
if (!meta) {
|
|
304
|
+
this._log.info('Could not gc because we were not able to load meta');
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
const promises = [];
|
|
308
|
+
const deets = {
|
|
309
|
+
gcOpts: this._gcOpts,
|
|
310
|
+
keys,
|
|
311
|
+
sacredKeys,
|
|
312
|
+
removed: [],
|
|
313
|
+
metaRemoved: [],
|
|
314
|
+
removedMissingCount: 0,
|
|
315
|
+
removedOldCount: 0,
|
|
316
|
+
removedThresholdCount: 0,
|
|
317
|
+
removedSizeCount: 0,
|
|
318
|
+
};
|
|
319
|
+
// First, remove all keys we don't know about
|
|
320
|
+
for (const key of keys) {
|
|
321
|
+
if (sacredKeys.has(key) || key in meta.objects) {
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
this._log.info('Lost track of key in meta', key);
|
|
325
|
+
promises.push(this._persister.removeItem(key));
|
|
326
|
+
deets.removed.push(key);
|
|
327
|
+
deets.removedMissingCount++;
|
|
328
|
+
}
|
|
329
|
+
// Remove anything over the max age
|
|
330
|
+
const now = Date.now();
|
|
331
|
+
for (const [k, m] of Object.entries(meta.objects)) {
|
|
332
|
+
if (!sacredKeys.has(k) &&
|
|
333
|
+
m.updatedAt < now - this._gcOpts.maxAgeMs) {
|
|
334
|
+
promises.push(this._persister.removeItem(k));
|
|
335
|
+
delete meta.objects[k];
|
|
336
|
+
deets.removed.push(k);
|
|
337
|
+
deets.removedOldCount++;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
// Keep queries under max queries
|
|
341
|
+
const maxEntries = Object.entries(meta.objects);
|
|
342
|
+
maxEntries.sort(([_k_a, a_meta], [_k_b, b_meta]) => {
|
|
343
|
+
return a_meta.updatedAt - b_meta.updatedAt;
|
|
344
|
+
});
|
|
345
|
+
const deletableMaxEntries = maxEntries.filter(([x]) => !sacredKeys.has(x));
|
|
346
|
+
if (maxEntries.length > this._gcOpts.maxEntries) {
|
|
347
|
+
for (const [k] of deletableMaxEntries.slice(0, maxEntries.length - this._gcOpts.maxEntries)) {
|
|
348
|
+
promises.push(this._persister.removeItem(k));
|
|
349
|
+
delete meta.objects[k];
|
|
350
|
+
deets.removed.push(k);
|
|
351
|
+
deets.removedThresholdCount++;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
// Remove oldest entries until we are under max size
|
|
355
|
+
const delEntries = Object.entries(meta.objects);
|
|
356
|
+
delEntries.sort(([_k_a, a_meta], [_k_b, b_meta]) => {
|
|
357
|
+
return a_meta.updatedAt - b_meta.updatedAt;
|
|
358
|
+
});
|
|
359
|
+
const deletableDelEntries = delEntries.filter(([x]) => !sacredKeys.has(x));
|
|
360
|
+
let currentSize = delEntries.reduce((acc, [_k, m]) => {
|
|
361
|
+
return acc + m.size;
|
|
362
|
+
}, 0);
|
|
363
|
+
while (currentSize > 0 &&
|
|
364
|
+
currentSize > this._gcOpts.maxSize &&
|
|
365
|
+
deletableDelEntries.length) {
|
|
366
|
+
const [[k, m]] = deletableDelEntries.splice(0, 1);
|
|
367
|
+
currentSize -= m.size;
|
|
332
368
|
promises.push(this._persister.removeItem(k));
|
|
333
369
|
delete meta.objects[k];
|
|
334
370
|
deets.removed.push(k);
|
|
335
|
-
deets.
|
|
371
|
+
deets.removedSizeCount++;
|
|
336
372
|
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
});
|
|
343
|
-
const deletableDelEntries = delEntries.filter(([x]) => !sacredKeys.has(x));
|
|
344
|
-
let currentSize = delEntries.reduce((acc, [_k, m]) => {
|
|
345
|
-
return acc + m.size;
|
|
346
|
-
}, 0);
|
|
347
|
-
while (currentSize > 0 &&
|
|
348
|
-
currentSize > this._gcOpts.maxSize &&
|
|
349
|
-
deletableDelEntries.length) {
|
|
350
|
-
const [[k, m]] = deletableDelEntries.splice(0, 1);
|
|
351
|
-
currentSize -= m.size;
|
|
352
|
-
promises.push(this._persister.removeItem(k));
|
|
353
|
-
delete meta.objects[k];
|
|
354
|
-
deets.removed.push(k);
|
|
355
|
-
deets.removedSizeCount++;
|
|
356
|
-
}
|
|
357
|
-
// Update meta to remove keys that are no longer in the store
|
|
358
|
-
for (const k of Object.keys(meta.objects)) {
|
|
359
|
-
if (!keys.has(k) && !sacredKeys.has(k)) {
|
|
360
|
-
delete meta.objects[k];
|
|
373
|
+
// Update meta to remove keys that are no longer in the store
|
|
374
|
+
for (const k of Object.keys(meta.objects)) {
|
|
375
|
+
if (!keys.has(k) && !sacredKeys.has(k)) {
|
|
376
|
+
delete meta.objects[k];
|
|
377
|
+
}
|
|
361
378
|
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
379
|
+
if (deets.removed.length || deets.metaRemoved.length) {
|
|
380
|
+
// Trigger a flush of the meta
|
|
381
|
+
promises.push(this._enqueuePersist({ skipGc: true }));
|
|
382
|
+
}
|
|
383
|
+
this._log.info('Completed GC', deets);
|
|
384
|
+
yield Promise.all(promises);
|
|
385
|
+
return deets;
|
|
386
|
+
});
|
|
370
387
|
}
|
|
371
388
|
// Schedules a GC to run in one minute (unless it is already scheduled)
|
|
372
389
|
gc() {
|