@procedures/store 0.4.0 → 0.6.0
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/CHANGELOG.md +34 -0
- package/README.md +22 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/storage/api.d.ts +11 -0
- package/dist/storage/api.d.ts.map +1 -1
- package/dist/storage/api.js +36 -3
- package/dist/storage/api.js.map +1 -1
- package/dist/storage/hybrid.d.ts +43 -7
- package/dist/storage/hybrid.d.ts.map +1 -1
- package/dist/storage/hybrid.js +115 -35
- package/dist/storage/hybrid.js.map +1 -1
- package/dist/storage/synced-registry.d.ts +8 -1
- package/dist/storage/synced-registry.d.ts.map +1 -1
- package/dist/storage/synced-registry.js +25 -4
- package/dist/storage/synced-registry.js.map +1 -1
- package/package.json +3 -3
- package/src/storage/api.ts +35 -3
- package/src/storage/hybrid.ts +108 -32
- package/src/storage/synced-registry.ts +26 -6
package/dist/storage/api.d.ts
CHANGED
|
@@ -104,7 +104,13 @@ export interface ApiStorageOptions {
|
|
|
104
104
|
export declare class ApiStorage<T> implements CollectionStorage<T> {
|
|
105
105
|
private client;
|
|
106
106
|
private options;
|
|
107
|
+
private closed;
|
|
107
108
|
constructor(client: Client, options: ApiStorageOptions);
|
|
109
|
+
/**
|
|
110
|
+
* The item of an id. For the core collection procedures, the call asks for `{ found, value }`,
|
|
111
|
+
* so a stored `null` reads back as `null`. A custom `service` or `get` operation gets `{ id }`,
|
|
112
|
+
* and its `null` reads back as `undefined`.
|
|
113
|
+
*/
|
|
108
114
|
get(id: string): Promise<T | undefined>;
|
|
109
115
|
getAll(): Promise<T[]>;
|
|
110
116
|
/** Every item with its id, from the `entries` procedure of the collection (roadmap R2). */
|
|
@@ -124,6 +130,11 @@ export declare class ApiStorage<T> implements CollectionStorage<T> {
|
|
|
124
130
|
setBatch(items: Array<[string, T]>): Promise<void>;
|
|
125
131
|
deleteBatch(ids: string[]): Promise<number>;
|
|
126
132
|
getBatch(ids: string[]): Promise<Map<string, T>>;
|
|
133
|
+
/**
|
|
134
|
+
* This method closes the storage. After it, each operation rejects, and a second `close()` does
|
|
135
|
+
* nothing. The items stay on the server. The client belongs to the caller, unless the option
|
|
136
|
+
* `closeClient` gave it to the storage.
|
|
137
|
+
*/
|
|
127
138
|
close(): Promise<void>;
|
|
128
139
|
getMetadata(): Promise<StorageMetadata>;
|
|
129
140
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/storage/api.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAClG,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAGjD,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE/D;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,UAAU,CAAC,EAAE;QACX,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IAEF;;;OAGG;IACH,OAAO,CAAC,EAAE,QAAQ,CAAC;IAEnB;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAEzB;;;OAGG;IACH,UAAU,CAAC,EAAE,QAAQ,CAAC;IAEtB;;OAEG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IAErB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/storage/api.ts"],"names":[],"mappings":"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"}
|
package/dist/storage/api.js
CHANGED
|
@@ -31,6 +31,16 @@ function untilAborted(promise, signal, describe) {
|
|
|
31
31
|
});
|
|
32
32
|
});
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* True for the output `{ found, value }` of the core procedure `get` with `found: true`: an
|
|
36
|
+
* object with a boolean `found`, and no key other than `found` and `value`.
|
|
37
|
+
*/
|
|
38
|
+
function isFoundOutput(value) {
|
|
39
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
40
|
+
return false;
|
|
41
|
+
const record = value;
|
|
42
|
+
return typeof record["found"] === "boolean" && Object.keys(record).every((key) => key === "found" || key === "value");
|
|
43
|
+
}
|
|
34
44
|
/**
|
|
35
45
|
* API storage backed by universal client.
|
|
36
46
|
*
|
|
@@ -61,6 +71,7 @@ function untilAborted(promise, signal, describe) {
|
|
|
61
71
|
export class ApiStorage {
|
|
62
72
|
client;
|
|
63
73
|
options;
|
|
74
|
+
closed = false;
|
|
64
75
|
constructor(client, options) {
|
|
65
76
|
const service = options.service ?? (options.collection !== undefined ? `collections.${options.collection}` : undefined);
|
|
66
77
|
if (!service) {
|
|
@@ -91,14 +102,27 @@ export class ApiStorage {
|
|
|
91
102
|
retryDelay: optionalMs(options.retryDelay, "retryDelay") ?? 100,
|
|
92
103
|
...(options.signal !== undefined && { signal: options.signal }),
|
|
93
104
|
closeClient: options.closeClient ?? false,
|
|
105
|
+
// A custom service can refuse an unknown input field: it gets the input { id }
|
|
106
|
+
askFound: options.service === undefined && (options.operations?.get ?? "get") === "get",
|
|
94
107
|
};
|
|
95
108
|
}
|
|
96
109
|
//
|
|
97
110
|
// ═══ Read Operations ═══
|
|
98
111
|
//
|
|
112
|
+
/**
|
|
113
|
+
* The item of an id. For the core collection procedures, the call asks for `{ found, value }`,
|
|
114
|
+
* so a stored `null` reads back as `null`. A custom `service` or `get` operation gets `{ id }`,
|
|
115
|
+
* and its `null` reads back as `undefined`.
|
|
116
|
+
*/
|
|
99
117
|
async get(id) {
|
|
100
|
-
|
|
101
|
-
|
|
118
|
+
if (!this.options.askFound) {
|
|
119
|
+
return (await this.call("get", { id })) ?? undefined;
|
|
120
|
+
}
|
|
121
|
+
const result = await this.call("get", { id, found: true });
|
|
122
|
+
if (isFoundOutput(result))
|
|
123
|
+
return result.found ? result.value : undefined;
|
|
124
|
+
// A server before `found` ignores it and gives the item, or null for a missing id
|
|
125
|
+
return (result ?? undefined);
|
|
102
126
|
}
|
|
103
127
|
async getAll() {
|
|
104
128
|
const values = await this.call("getAll", {});
|
|
@@ -178,8 +202,15 @@ export class ApiStorage {
|
|
|
178
202
|
//
|
|
179
203
|
// ═══ Lifecycle & Metadata ═══
|
|
180
204
|
//
|
|
205
|
+
/**
|
|
206
|
+
* This method closes the storage. After it, each operation rejects, and a second `close()` does
|
|
207
|
+
* nothing. The items stay on the server. The client belongs to the caller, unless the option
|
|
208
|
+
* `closeClient` gave it to the storage.
|
|
209
|
+
*/
|
|
181
210
|
async close() {
|
|
182
|
-
|
|
211
|
+
if (this.closed)
|
|
212
|
+
return;
|
|
213
|
+
this.closed = true;
|
|
183
214
|
if (this.options.closeClient) {
|
|
184
215
|
await this.client.close();
|
|
185
216
|
}
|
|
@@ -203,6 +234,8 @@ export class ApiStorage {
|
|
|
203
234
|
* Make an RPC call via the universal client, with the timeout, the signal and the retries.
|
|
204
235
|
*/
|
|
205
236
|
async call(operation, payload) {
|
|
237
|
+
if (this.closed)
|
|
238
|
+
throw new Error(`The ApiStorage of ${this.options.service} is closed`);
|
|
206
239
|
const method = {
|
|
207
240
|
service: this.options.service,
|
|
208
241
|
operation: this.options.operations[operation] ?? operation,
|
package/dist/storage/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/storage/api.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,EAAE,UAAU,EAAiB,MAAM,oBAAoB,CAAC;AA4E/D,mFAAmF;AACnF,SAAS,WAAW,CAAC,KAAc;IACjC,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACb,KAAiC,CAAC,SAAS,KAAK,IAAI,CACtD,CAAC;AACJ,CAAC;AAED,2DAA2D;AAC3D,SAAS,YAAY,CAAI,OAAmB,EAAE,MAA+B,EAAE,QAAqB;IAClG,IAAI,CAAC,MAAM;QAAE,OAAO,OAAO,CAAC;IAC5B,IAAI,MAAM,CAAC,OAAO;QAAE,OAAO,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;IACtD,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACxC,MAAM,OAAO,GAAG,GAAS,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC/C,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,OAAO,CAAC,IAAI,CACV,CAAC,KAAK,EAAE,EAAE;YACR,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC7C,OAAO,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC,EACD,CAAC,KAAc,EAAE,EAAE;YACjB,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC7C,MAAM,CAAC,KAAK,CAAC,CAAC;QAChB,CAAC,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,OAAO,UAAU;IACb,MAAM,CAAS;IACf,OAAO,
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/storage/api.ts"],"names":[],"mappings":"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"}
|
package/dist/storage/hybrid.d.ts
CHANGED
|
@@ -16,6 +16,10 @@
|
|
|
16
16
|
* - A sync asks for the changes since a version when the remote has `getChangesSince`.
|
|
17
17
|
* - With `versionOf`, a conflict is a change on both sides, and `conflictResolution` decides.
|
|
18
18
|
* - `pullInterval` keeps the local copy fresh.
|
|
19
|
+
* - Each write takes a copy of the value (`structuredClone`), for the local copy, the queue and the
|
|
20
|
+
* remote. The reads give the copies of the local copy, or of the remote in `remote-only` mode.
|
|
21
|
+
* - A full sync reads the local ids with `getIds()`, so it does not copy each local item.
|
|
22
|
+
* - After `close()`, each operation rejects, and a second `close()` does nothing.
|
|
19
23
|
*/
|
|
20
24
|
import type { CollectionStorage, StorageMetadata } from "@procedures/collections";
|
|
21
25
|
import { type Duration } from "@procedures/client";
|
|
@@ -198,7 +202,8 @@ export declare class ModeSwitchError extends Error {
|
|
|
198
202
|
/**
|
|
199
203
|
* A storage for the local copy of a `HybridStorage` (roadmap R45): a collection storage that gives
|
|
200
204
|
* its entries. A durable one, for example `SqliteStorage` of `@procedures/sqlite`, keeps the local
|
|
201
|
-
* copy after a restart.
|
|
205
|
+
* copy after a restart. With `getIds()`, a full sync reads the local ids without a copy of the
|
|
206
|
+
* values.
|
|
202
207
|
*/
|
|
203
208
|
export type LocalCopyStorage<T> = CollectionStorage<T> & {
|
|
204
209
|
getEntries(): Promise<Array<[string, T]>>;
|
|
@@ -264,7 +269,10 @@ export declare class HybridStorage<T> implements CollectionStorage<T> {
|
|
|
264
269
|
private active;
|
|
265
270
|
private idleWaiters;
|
|
266
271
|
private isOnline;
|
|
272
|
+
/** True after `close()`: each operation rejects */
|
|
267
273
|
private closed;
|
|
274
|
+
/** The work of the first `close()` */
|
|
275
|
+
private closing;
|
|
268
276
|
/** A counter of local writes for each id, so a sync does not restore an older remote value */
|
|
269
277
|
private readonly writeVersions;
|
|
270
278
|
private clearVersion;
|
|
@@ -310,16 +318,27 @@ export declare class HybridStorage<T> implements CollectionStorage<T> {
|
|
|
310
318
|
getAll(): Promise<T[]>;
|
|
311
319
|
/** Every item with its id. */
|
|
312
320
|
getEntries(): Promise<Array<[string, T]>>;
|
|
321
|
+
/**
|
|
322
|
+
* The ids of the items, in the order of the entries: the ids of the local copy, or of the remote
|
|
323
|
+
* in `remote-only` mode. The ids come without a copy of the values when the storage under them
|
|
324
|
+
* has `getIds()`.
|
|
325
|
+
*/
|
|
326
|
+
getIds(): Promise<string[]>;
|
|
313
327
|
find(predicate: (item: T) => boolean): Promise<T[]>;
|
|
314
328
|
has(id: string): Promise<boolean>;
|
|
315
329
|
size(): Promise<number>;
|
|
316
330
|
getBatch(ids: string[]): Promise<Map<string, T>>;
|
|
317
331
|
/** A read of the remote-only mode. A queue that a restart loaded reaches the remote first. */
|
|
318
332
|
private remoteRead;
|
|
319
|
-
|
|
333
|
+
/**
|
|
334
|
+
* This method sets an item. The storage takes a copy of the value, so a later change of the
|
|
335
|
+
* value does not change the local copy, the queue or the remote write.
|
|
336
|
+
*/
|
|
337
|
+
set(id: string, written: T): Promise<void>;
|
|
320
338
|
delete(id: string): Promise<boolean>;
|
|
321
339
|
clear(): Promise<void>;
|
|
322
|
-
|
|
340
|
+
/** This method sets several items. The storage takes a copy of each value, as `set` does. */
|
|
341
|
+
setBatch(written: Array<[string, T]>): Promise<void>;
|
|
323
342
|
deleteBatch(ids: string[]): Promise<number>;
|
|
324
343
|
/**
|
|
325
344
|
* One write, in the mode of the storage. The result is the result of the local copy, or of the
|
|
@@ -375,12 +394,25 @@ export declare class HybridStorage<T> implements CollectionStorage<T> {
|
|
|
375
394
|
* Force a full sync (both directions).
|
|
376
395
|
*/
|
|
377
396
|
sync(): Promise<void>;
|
|
378
|
-
/**
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
397
|
+
/** The pull of `syncFromRemote()`, after the syncs that run. */
|
|
398
|
+
private pull;
|
|
399
|
+
/** The push of `syncToRemote()`, after the syncs that run. */
|
|
400
|
+
private push;
|
|
401
|
+
/** The error of an operation after `close()`. */
|
|
402
|
+
private closedError;
|
|
403
|
+
/**
|
|
404
|
+
* This method closes the storage.
|
|
405
|
+
*
|
|
406
|
+
* - It stops the timers, and waits for the operations, the mode switch and the syncs that run.
|
|
407
|
+
* - It sends the queue (not in `local-only` mode). The queue store keeps the operations that
|
|
408
|
+
* the remote did not take.
|
|
409
|
+
* - It closes the remote and the local copy. A durable local copy keeps its items.
|
|
410
|
+
* - After it, each operation rejects. A second `close()` does nothing: it gives the promise of
|
|
411
|
+
* the first one, without its error.
|
|
382
412
|
*/
|
|
383
413
|
close(): Promise<void>;
|
|
414
|
+
/** The work of `close()`. */
|
|
415
|
+
private shutDown;
|
|
384
416
|
/**
|
|
385
417
|
* The metadata of the storage. `size` is the result of `size()`: the number of items of the
|
|
386
418
|
* storage, also in `remote-only` mode. `stats.localSize` is the number of items of the local
|
|
@@ -435,6 +467,10 @@ export declare class HybridStorage<T> implements CollectionStorage<T> {
|
|
|
435
467
|
* so the remote list without ids emptied the cache (roadmap R2).
|
|
436
468
|
*/
|
|
437
469
|
private remoteEntries;
|
|
470
|
+
/** The ids of the local copy: from `getIds()` when it has it, without a copy of the values. */
|
|
471
|
+
private localIds;
|
|
472
|
+
/** The ids of the remote: from `getIds()` when it has it, or else from its entries. */
|
|
473
|
+
private remoteIds;
|
|
438
474
|
/**
|
|
439
475
|
* This method sends the queue. The operations that reached the remote leave the queue. The queue store
|
|
440
476
|
* gets the change at the end.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hybrid.d.ts","sourceRoot":"","sources":["../../src/storage/hybrid.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"hybrid.d.ts","sourceRoot":"","sources":["../../src/storage/hybrid.ts"],"names":[],"mappings":"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"}
|
package/dist/storage/hybrid.js
CHANGED
|
@@ -16,6 +16,10 @@
|
|
|
16
16
|
* - A sync asks for the changes since a version when the remote has `getChangesSince`.
|
|
17
17
|
* - With `versionOf`, a conflict is a change on both sides, and `conflictResolution` decides.
|
|
18
18
|
* - `pullInterval` keeps the local copy fresh.
|
|
19
|
+
* - Each write takes a copy of the value (`structuredClone`), for the local copy, the queue and the
|
|
20
|
+
* remote. The reads give the copies of the local copy, or of the remote in `remote-only` mode.
|
|
21
|
+
* - A full sync reads the local ids with `getIds()`, so it does not copy each local item.
|
|
22
|
+
* - After `close()`, each operation rejects, and a second `close()` does nothing.
|
|
19
23
|
*/
|
|
20
24
|
import { InMemoryStorage } from "@procedures/collections";
|
|
21
25
|
import { optionalMs } from "@procedures/client";
|
|
@@ -167,7 +171,10 @@ export class HybridStorage {
|
|
|
167
171
|
active = 0;
|
|
168
172
|
idleWaiters = [];
|
|
169
173
|
isOnline = true;
|
|
174
|
+
/** True after `close()`: each operation rejects */
|
|
170
175
|
closed = false;
|
|
176
|
+
/** The work of the first `close()` */
|
|
177
|
+
closing;
|
|
171
178
|
/** A counter of local writes for each id, so a sync does not restore an older remote value */
|
|
172
179
|
writeVersions = new Map();
|
|
173
180
|
clearVersion = 0;
|
|
@@ -229,6 +236,8 @@ export class HybridStorage {
|
|
|
229
236
|
*/
|
|
230
237
|
async setMode(mode) {
|
|
231
238
|
const target = checkMode(mode);
|
|
239
|
+
if (this.closed)
|
|
240
|
+
throw this.closedError();
|
|
232
241
|
const previous = this.gate;
|
|
233
242
|
let release;
|
|
234
243
|
this.gate = new Promise((resolve) => (release = resolve));
|
|
@@ -288,7 +297,9 @@ export class HybridStorage {
|
|
|
288
297
|
const push = this.mode === "write-back" && this.options.syncInterval > 0;
|
|
289
298
|
if (push && !this.syncTimer) {
|
|
290
299
|
this.syncTimer = setInterval(() => {
|
|
291
|
-
this.
|
|
300
|
+
if (this.closed)
|
|
301
|
+
return;
|
|
302
|
+
this.push().catch((err) => {
|
|
292
303
|
console.error("Periodic sync failed:", err);
|
|
293
304
|
});
|
|
294
305
|
}, this.options.syncInterval);
|
|
@@ -302,7 +313,9 @@ export class HybridStorage {
|
|
|
302
313
|
const pull = this.options.pullInterval > 0 && (this.mode === "write-through" || this.mode === "write-back");
|
|
303
314
|
if (pull && !this.pullTimer) {
|
|
304
315
|
this.pullTimer = setInterval(() => {
|
|
305
|
-
this.
|
|
316
|
+
if (this.closed)
|
|
317
|
+
return;
|
|
318
|
+
this.pull().catch((err) => {
|
|
306
319
|
console.error("Periodic pull failed:", err);
|
|
307
320
|
});
|
|
308
321
|
}, this.options.pullInterval);
|
|
@@ -364,6 +377,14 @@ export class HybridStorage {
|
|
|
364
377
|
async getEntries() {
|
|
365
378
|
return this.run(true, () => (this.mode === "remote-only" ? this.remoteRead(() => this.remoteEntries()) : this.local.getEntries()));
|
|
366
379
|
}
|
|
380
|
+
/**
|
|
381
|
+
* The ids of the items, in the order of the entries: the ids of the local copy, or of the remote
|
|
382
|
+
* in `remote-only` mode. The ids come without a copy of the values when the storage under them
|
|
383
|
+
* has `getIds()`.
|
|
384
|
+
*/
|
|
385
|
+
async getIds() {
|
|
386
|
+
return this.run(true, () => (this.mode === "remote-only" ? this.remoteRead(() => this.remoteIds()) : this.localIds()));
|
|
387
|
+
}
|
|
367
388
|
async find(predicate) {
|
|
368
389
|
return this.run(true, () => this.mode === "remote-only" ? this.remoteRead(() => this.remote.find(predicate)) : this.local.find(predicate));
|
|
369
390
|
}
|
|
@@ -394,7 +415,12 @@ export class HybridStorage {
|
|
|
394
415
|
//
|
|
395
416
|
// ═══ Write Operations ═══
|
|
396
417
|
//
|
|
397
|
-
|
|
418
|
+
/**
|
|
419
|
+
* This method sets an item. The storage takes a copy of the value, so a later change of the
|
|
420
|
+
* value does not change the local copy, the queue or the remote write.
|
|
421
|
+
*/
|
|
422
|
+
async set(id, written) {
|
|
423
|
+
const value = structuredClone(written);
|
|
398
424
|
await this.write("set", { id, value }, [id], async () => {
|
|
399
425
|
this.bump(id);
|
|
400
426
|
await this.local.set(id, value);
|
|
@@ -415,7 +441,9 @@ export class HybridStorage {
|
|
|
415
441
|
//
|
|
416
442
|
// ═══ Bulk Operations ═══
|
|
417
443
|
//
|
|
418
|
-
|
|
444
|
+
/** This method sets several items. The storage takes a copy of each value, as `set` does. */
|
|
445
|
+
async setBatch(written) {
|
|
446
|
+
const items = written.map(([id, value]) => [id, structuredClone(value)]);
|
|
419
447
|
await this.write("setBatch", { items }, items.map(([id]) => id), async () => {
|
|
420
448
|
for (const [id] of items)
|
|
421
449
|
this.bump(id);
|
|
@@ -559,13 +587,9 @@ export class HybridStorage {
|
|
|
559
587
|
* - Syncs run one at a time.
|
|
560
588
|
*/
|
|
561
589
|
syncFromRemote() {
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
throw this.loadError;
|
|
566
|
-
if (this.mode === "write-through" || this.mode === "write-back")
|
|
567
|
-
await this.pullRemote(false);
|
|
568
|
-
});
|
|
590
|
+
if (this.closed)
|
|
591
|
+
return Promise.reject(this.closedError());
|
|
592
|
+
return this.pull();
|
|
569
593
|
}
|
|
570
594
|
/**
|
|
571
595
|
* Sync all pending offline operations to remote.
|
|
@@ -574,13 +598,9 @@ export class HybridStorage {
|
|
|
574
598
|
* the call does nothing.
|
|
575
599
|
*/
|
|
576
600
|
syncToRemote() {
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
throw this.loadError;
|
|
581
|
-
if (this.mode !== "local-only")
|
|
582
|
-
await this.pushQueue();
|
|
583
|
-
});
|
|
601
|
+
if (this.closed)
|
|
602
|
+
return Promise.reject(this.closedError());
|
|
603
|
+
return this.push();
|
|
584
604
|
}
|
|
585
605
|
/**
|
|
586
606
|
* This method sends the queue to the remote (roadmap R28). `ProcedureServer.useStorage` uses it. In
|
|
@@ -596,16 +616,52 @@ export class HybridStorage {
|
|
|
596
616
|
await this.syncToRemote();
|
|
597
617
|
await this.syncFromRemote();
|
|
598
618
|
}
|
|
619
|
+
/** The pull of `syncFromRemote()`, after the syncs that run. */
|
|
620
|
+
pull() {
|
|
621
|
+
return this.serialize(async () => {
|
|
622
|
+
await this.loaded;
|
|
623
|
+
if (this.loadError)
|
|
624
|
+
throw this.loadError;
|
|
625
|
+
if (this.mode === "write-through" || this.mode === "write-back")
|
|
626
|
+
await this.pullRemote(false);
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
/** The push of `syncToRemote()`, after the syncs that run. */
|
|
630
|
+
push() {
|
|
631
|
+
return this.serialize(async () => {
|
|
632
|
+
await this.loaded;
|
|
633
|
+
if (this.loadError)
|
|
634
|
+
throw this.loadError;
|
|
635
|
+
if (this.mode !== "local-only")
|
|
636
|
+
await this.pushQueue();
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
/** The error of an operation after `close()`. */
|
|
640
|
+
closedError() {
|
|
641
|
+
return new Error("The HybridStorage is closed");
|
|
642
|
+
}
|
|
599
643
|
//
|
|
600
644
|
// ═══ Lifecycle & Metadata ═══
|
|
601
645
|
//
|
|
602
646
|
/**
|
|
603
|
-
* This method
|
|
604
|
-
*
|
|
605
|
-
*
|
|
647
|
+
* This method closes the storage.
|
|
648
|
+
*
|
|
649
|
+
* - It stops the timers, and waits for the operations, the mode switch and the syncs that run.
|
|
650
|
+
* - It sends the queue (not in `local-only` mode). The queue store keeps the operations that
|
|
651
|
+
* the remote did not take.
|
|
652
|
+
* - It closes the remote and the local copy. A durable local copy keeps its items.
|
|
653
|
+
* - After it, each operation rejects. A second `close()` does nothing: it gives the promise of
|
|
654
|
+
* the first one, without its error.
|
|
606
655
|
*/
|
|
607
|
-
|
|
656
|
+
close() {
|
|
657
|
+
if (this.closing)
|
|
658
|
+
return this.closing.catch(() => undefined);
|
|
608
659
|
this.closed = true;
|
|
660
|
+
this.closing = this.shutDown();
|
|
661
|
+
return this.closing;
|
|
662
|
+
}
|
|
663
|
+
/** The work of `close()`. */
|
|
664
|
+
async shutDown() {
|
|
609
665
|
for (const timer of [this.syncTimer, this.pullTimer]) {
|
|
610
666
|
if (timer)
|
|
611
667
|
clearInterval(timer);
|
|
@@ -617,15 +673,20 @@ export class HybridStorage {
|
|
|
617
673
|
this.drainTimer = null;
|
|
618
674
|
}
|
|
619
675
|
await this.loaded;
|
|
620
|
-
//
|
|
621
|
-
|
|
676
|
+
// The operations and the switch that started before close() end first
|
|
677
|
+
await this.gate;
|
|
678
|
+
await this.idle();
|
|
679
|
+
// After the syncs that run: send the pending operations
|
|
680
|
+
await this.serialize(async () => {
|
|
681
|
+
if (this.loadError || this.offlineOps.length === 0 || this.mode === "local-only")
|
|
682
|
+
return;
|
|
622
683
|
try {
|
|
623
|
-
await this.
|
|
684
|
+
await this.pushQueue();
|
|
624
685
|
}
|
|
625
686
|
catch (error) {
|
|
626
687
|
console.error("Failed to sync before close:", error);
|
|
627
688
|
}
|
|
628
|
-
}
|
|
689
|
+
});
|
|
629
690
|
await this.storeChain;
|
|
630
691
|
// Close remote storage (an ApiStorage leaves the caller's client open)
|
|
631
692
|
try {
|
|
@@ -672,6 +733,8 @@ export class HybridStorage {
|
|
|
672
733
|
* and never during a mode switch.
|
|
673
734
|
*/
|
|
674
735
|
async run(read, work) {
|
|
736
|
+
if (this.closed)
|
|
737
|
+
throw this.closedError();
|
|
675
738
|
await (read ? this.ready : this.loaded);
|
|
676
739
|
for (;;) {
|
|
677
740
|
const gate = this.gate;
|
|
@@ -680,6 +743,9 @@ export class HybridStorage {
|
|
|
680
743
|
if (this.gate === gate)
|
|
681
744
|
break;
|
|
682
745
|
}
|
|
746
|
+
// close() started while this operation waited
|
|
747
|
+
if (this.closed)
|
|
748
|
+
throw this.closedError();
|
|
683
749
|
if (this.loadError)
|
|
684
750
|
throw this.loadError;
|
|
685
751
|
this.active++;
|
|
@@ -729,16 +795,17 @@ export class HybridStorage {
|
|
|
729
795
|
}
|
|
730
796
|
/** The first sync: send the loaded queue, then read the remote. */
|
|
731
797
|
async initialSync() {
|
|
732
|
-
|
|
798
|
+
// A close() before the first sync: the storage makes no remote call
|
|
799
|
+
if (this.loadError || this.closed)
|
|
733
800
|
return;
|
|
734
801
|
if (this.options.syncOnInit && this.mode !== "local-only") {
|
|
735
802
|
if (this.offlineOps.length > 0) {
|
|
736
|
-
await this.
|
|
803
|
+
await this.push().catch((err) => {
|
|
737
804
|
console.error("Failed to send the queue on init:", err);
|
|
738
805
|
});
|
|
739
806
|
}
|
|
740
|
-
if (this.mode === "write-through" || this.mode === "write-back") {
|
|
741
|
-
await this.
|
|
807
|
+
if (!this.closed && (this.mode === "write-through" || this.mode === "write-back")) {
|
|
808
|
+
await this.pull().catch((err) => {
|
|
742
809
|
console.error("Failed to sync on init:", err);
|
|
743
810
|
});
|
|
744
811
|
}
|
|
@@ -796,10 +863,9 @@ export class HybridStorage {
|
|
|
796
863
|
if (await this.pullItem(id, item, changedLocally, conflicts))
|
|
797
864
|
queueChanged = true;
|
|
798
865
|
}
|
|
799
|
-
// The remote deleted these items
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
: changes.deleted;
|
|
866
|
+
// The remote deleted these items. A full pull reads only the local ids: before, it read each
|
|
867
|
+
// local entry, and the local copy copied each value for it.
|
|
868
|
+
const gone = changes.full ? (await this.localIds()).filter((id) => !remoteIds.has(id)) : changes.deleted;
|
|
803
869
|
for (const id of gone) {
|
|
804
870
|
if (await this.pullDelete(id, changedLocally, conflicts))
|
|
805
871
|
queueChanged = true;
|
|
@@ -997,6 +1063,18 @@ export class HybridStorage {
|
|
|
997
1063
|
throw new MissingKeysError(missing);
|
|
998
1064
|
return entries;
|
|
999
1065
|
}
|
|
1066
|
+
/** The ids of the local copy: from `getIds()` when it has it, without a copy of the values. */
|
|
1067
|
+
async localIds() {
|
|
1068
|
+
if (this.local.getIds)
|
|
1069
|
+
return this.local.getIds();
|
|
1070
|
+
return (await this.local.getEntries()).map(([id]) => id);
|
|
1071
|
+
}
|
|
1072
|
+
/** The ids of the remote: from `getIds()` when it has it, or else from its entries. */
|
|
1073
|
+
async remoteIds() {
|
|
1074
|
+
if (this.remote.getIds)
|
|
1075
|
+
return this.remote.getIds();
|
|
1076
|
+
return (await this.remoteEntries()).map(([id]) => id);
|
|
1077
|
+
}
|
|
1000
1078
|
/**
|
|
1001
1079
|
* This method sends the queue. The operations that reached the remote leave the queue. The queue store
|
|
1002
1080
|
* gets the change at the end.
|
|
@@ -1327,7 +1405,9 @@ export class HybridStorage {
|
|
|
1327
1405
|
const delay = this.options.syncInterval > 0 ? this.options.syncInterval : 5000;
|
|
1328
1406
|
this.drainTimer = setTimeout(() => {
|
|
1329
1407
|
this.drainTimer = null;
|
|
1330
|
-
|
|
1408
|
+
if (this.closed)
|
|
1409
|
+
return;
|
|
1410
|
+
this.push().catch(() => this.scheduleDrain());
|
|
1331
1411
|
}, delay);
|
|
1332
1412
|
this.drainTimer.unref?.();
|
|
1333
1413
|
}
|