@procedures/store 0.52.1 → 0.52.3
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 +20 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/browser.d.ts +1 -1
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js.map +1 -1
- package/dist/storage/hybrid.d.ts +65 -0
- package/dist/storage/hybrid.d.ts.map +1 -1
- package/dist/storage/hybrid.js +204 -7
- package/dist/storage/hybrid.js.map +1 -1
- package/dist/storage/index.d.ts +1 -1
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/queue.d.ts +6 -0
- package/dist/storage/queue.d.ts.map +1 -1
- package/dist/storage/queue.js +40 -0
- package/dist/storage/queue.js.map +1 -1
- package/package.json +4 -4
- package/src/browser.ts +1 -0
- package/src/storage/hybrid.ts +224 -7
- package/src/storage/index.ts +1 -0
- package/src/storage/queue.ts +38 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queue.js","sourceRoot":"","sources":["../../src/storage/queue.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"queue.js","sourceRoot":"","sources":["../../src/storage/queue.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package",
|
|
3
3
|
"name": "@procedures/store",
|
|
4
|
-
"version": "0.52.
|
|
4
|
+
"version": "0.52.3",
|
|
5
5
|
"description": "A program store for procedure-as-data: save the programs that procedure.define makes, load them back after a restart, in memory, a JSON file, IndexedDB or a remote collection storage.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"program-store",
|
|
@@ -78,12 +78,12 @@
|
|
|
78
78
|
},
|
|
79
79
|
"dependencies": {
|
|
80
80
|
"@mark1russell7/service": "^0.6.0",
|
|
81
|
-
"@procedures/client": "0.52.
|
|
82
|
-
"@procedures/collections": "0.52.
|
|
81
|
+
"@procedures/client": "0.52.3",
|
|
82
|
+
"@procedures/collections": "0.52.3",
|
|
83
83
|
"zod": "^4.6.5"
|
|
84
84
|
},
|
|
85
85
|
"devDependencies": {
|
|
86
|
-
"@procedures/fs": "0.52.
|
|
86
|
+
"@procedures/fs": "0.52.3",
|
|
87
87
|
"@mark1russell7/cue": "^2.1.1",
|
|
88
88
|
"@types/node": "^22.0.0",
|
|
89
89
|
"fake-indexeddb": "^6.2.5",
|
package/src/browser.ts
CHANGED
package/src/storage/hybrid.ts
CHANGED
|
@@ -70,7 +70,7 @@ import {
|
|
|
70
70
|
} from "@procedures/client/query";
|
|
71
71
|
import { optionalMs, realClock, type Cancel, type Clock, type Duration } from "@procedures/client/browser";
|
|
72
72
|
import { backoffDelay } from "@mark1russell7/service/backoff";
|
|
73
|
-
import { MemoryQueueStore, idsOf, singlesOf, withoutId, type QueuedOperation, type QueueStore } from "./queue.js";
|
|
73
|
+
import { MemoryQueueStore, chunksOf, idsOf, singlesOf, withoutId, type QueuedOperation, type QueueStore } from "./queue.js";
|
|
74
74
|
import type { SyncError, SyncStatus } from "./types.js";
|
|
75
75
|
import type { RemoteChangeFeed, RemoteChangeHint, RemoteChanges } from "./feed.js";
|
|
76
76
|
import { isSyncState, type SyncStateStore } from "./sync-state.js";
|
|
@@ -259,6 +259,33 @@ export interface HybridStorageOptions {
|
|
|
259
259
|
*/
|
|
260
260
|
isTooLarge?: (error: unknown) => boolean;
|
|
261
261
|
|
|
262
|
+
/**
|
|
263
|
+
* This function reads the capacity of a send from an error of `isTooLarge` (roadmap CLI-121). It gives the units of
|
|
264
|
+
* the refused send and the capacity of the remote limit, or undefined. Only `pushBatch` reads it. The default reads
|
|
265
|
+
* the numbers `units` and `capacity` of the metadata of the error. A capacity refusal of a limit of the server gives
|
|
266
|
+
* these numbers.
|
|
267
|
+
*/
|
|
268
|
+
capacityOf?: (error: unknown) => { readonly units: number; readonly capacity: number } | undefined;
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* The merge of queued writes into one batch for each send (roadmap CLI-121). Without it, the push sends each queued
|
|
272
|
+
* write alone. With it, the push sends the run of sets at the head of the queue as one `setBatch`. It sends the run
|
|
273
|
+
* of deletes as one `deleteBatch`. Thus a first sync of many writes makes few remote calls.
|
|
274
|
+
*
|
|
275
|
+
* - A run stops at a write of another kind and at an id that the run already has. It also stops at a write that
|
|
276
|
+
* waits for the queue store, and at the caps of `PushBatch`. So the order of the writes of each id stays.
|
|
277
|
+
* - A delete of one id with a base version does not join a run, because `deleteBatch` sends no base versions.
|
|
278
|
+
* - A queued batch over the caps goes as batches within the caps. Set the caps within the capacity of a remote limit
|
|
279
|
+
* for each call. Then no send of a flush is larger than that capacity. A limit with a cost for each item is an example.
|
|
280
|
+
* - The writes leave the queue only after the remote took the batch.
|
|
281
|
+
* - When the remote refuses a merged batch or finds a conflict in it, the push sends each write of the run again
|
|
282
|
+
* alone. Thus `onRefused`, `onDropped` and the conflict policy get the same writes as without the merge.
|
|
283
|
+
* - A send of n ids with an error of `isTooLarge` lowers the cap of ids of each later send. With a capacity of
|
|
284
|
+
* `capacityOf`, the cap is n × capacity / units. Without it, the cap is half of n. The push then sends the same
|
|
285
|
+
* writes in smaller sends. Only a write of one id with this error leaves the queue, with the reason `too-large`.
|
|
286
|
+
*/
|
|
287
|
+
pushBatch?: PushBatch | undefined;
|
|
288
|
+
|
|
262
289
|
/**
|
|
263
290
|
* This hook gets each queued write that the remote refused (roadmap O67). The local copy of its
|
|
264
291
|
* ids gets the remote values again, except for an id that a later queued write changes. An
|
|
@@ -786,9 +813,54 @@ const defaultIsRefusal = (error: unknown): boolean => {
|
|
|
786
813
|
return typeof code === "string" && REFUSAL_CODES.has(code);
|
|
787
814
|
};
|
|
788
815
|
|
|
816
|
+
/** The caps of a merged send of the queue (roadmap CLI-121). */
|
|
817
|
+
export interface PushBatch {
|
|
818
|
+
/** The most ids in one merged send. The default is 100. */
|
|
819
|
+
readonly maxItems?: number | undefined;
|
|
820
|
+
/** The most characters of the JSON text of the writes in one merged send. The default is 1048576 (1 MiB). */
|
|
821
|
+
readonly maxBytes?: number | undefined;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
/** This function gives the caps of a merged send, with the defaults. It throws a `RangeError` for a cap that is not a whole number of 1 or more. */
|
|
825
|
+
function pushBatchOf(batch: PushBatch): { maxItems: number; maxBytes: number } {
|
|
826
|
+
const cap = (value: number | undefined, fallback: number, name: string): number => {
|
|
827
|
+
if (value === undefined) return fallback;
|
|
828
|
+
if (!Number.isInteger(value) || value < 1) throw new RangeError(`pushBatch.${name} must be a whole number of 1 or more, not ${String(value)}`);
|
|
829
|
+
return value;
|
|
830
|
+
};
|
|
831
|
+
return { maxItems: cap(batch.maxItems, 100, "maxItems"), maxBytes: cap(batch.maxBytes, 1_048_576, "maxBytes") };
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
/** This function gives the kind of a write in a merged send: `set` for a set or a set batch, `delete` for a delete or its batch. */
|
|
835
|
+
function mergeKind(op: QueuedOperation): "set" | "delete" | undefined {
|
|
836
|
+
if (op.type === "set" || op.type === "setBatch") return "set";
|
|
837
|
+
if (op.type === "delete" || op.type === "deleteBatch") return "delete";
|
|
838
|
+
return undefined;
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
/** This function gives one batch with the writes of a run, in their order (roadmap CLI-121). */
|
|
842
|
+
function mergedOperation(run: readonly QueuedOperation[]): QueuedOperation {
|
|
843
|
+
const timestamp = run[0]!.timestamp;
|
|
844
|
+
if (mergeKind(run[0]!) === "delete") return { type: "deleteBatch", data: { ids: run.flatMap(idsOf) }, timestamp };
|
|
845
|
+
const items = run.flatMap((op): Array<[string, unknown]> => {
|
|
846
|
+
const data = op.data as { id: string; value: unknown; items: Array<[string, unknown]> };
|
|
847
|
+
return op.type === "set" ? [[data.id, data.value]] : data.items;
|
|
848
|
+
});
|
|
849
|
+
return { type: "setBatch", data: { items }, timestamp };
|
|
850
|
+
}
|
|
851
|
+
|
|
789
852
|
/** The default of `isTooLarge`: an error with the code `PAYLOAD_TOO_LARGE` (roadmap CLI-108). */
|
|
790
853
|
const defaultIsTooLarge = (error: unknown): boolean => (error as { code?: unknown } | null | undefined)?.code === "PAYLOAD_TOO_LARGE";
|
|
791
854
|
|
|
855
|
+
/** The default of `capacityOf`: the numbers `units` and `capacity` of the metadata of the error, with units over the capacity. */
|
|
856
|
+
const defaultCapacityOf = (error: unknown): { units: number; capacity: number } | undefined => {
|
|
857
|
+
const metadata = (error as { metadata?: { units?: unknown; capacity?: unknown } | null } | null | undefined)?.metadata;
|
|
858
|
+
const units = metadata?.units;
|
|
859
|
+
const capacity = metadata?.capacity;
|
|
860
|
+
if (typeof units !== "number" || typeof capacity !== "number" || !Number.isFinite(units) || !Number.isFinite(capacity)) return undefined;
|
|
861
|
+
return capacity >= 1 && units > capacity ? { units, capacity } : undefined;
|
|
862
|
+
};
|
|
863
|
+
|
|
792
864
|
/** True when a remote does not know a procedure: an older server without `changes`. */
|
|
793
865
|
const isNotFound = (error: unknown): boolean =>
|
|
794
866
|
typeof error === "object" && error !== null && (error as { code?: unknown }).code === "NOT_FOUND";
|
|
@@ -1066,6 +1138,8 @@ export class HybridStorage<T> implements CollectionStorage<T> {
|
|
|
1066
1138
|
isUnavailable: (error: unknown) => boolean;
|
|
1067
1139
|
isRefusal: (error: unknown) => boolean;
|
|
1068
1140
|
isTooLarge: (error: unknown) => boolean;
|
|
1141
|
+
capacityOf: (error: unknown) => { readonly units: number; readonly capacity: number } | undefined;
|
|
1142
|
+
pushBatch?: { maxItems: number; maxBytes: number };
|
|
1069
1143
|
onRefused?: (refusal: QueueRefusal) => void | Promise<void>;
|
|
1070
1144
|
onDropped?: (drop: DroppedWrite) => void | Promise<void>;
|
|
1071
1145
|
};
|
|
@@ -1073,6 +1147,12 @@ export class HybridStorage<T> implements CollectionStorage<T> {
|
|
|
1073
1147
|
private offlineOps: QueuedOperation[] = [];
|
|
1074
1148
|
/** The operations in `offlineOps` that the queue store does not have yet */
|
|
1075
1149
|
private readonly unpersisted = new Set<QueuedOperation>();
|
|
1150
|
+
/** The count of operations at the head of the queue that the push sends at this time: more than 1 for a merged send (roadmap CLI-121) */
|
|
1151
|
+
private sendingCount = 0;
|
|
1152
|
+
/** The length of the JSON text of each queued operation, for the byte cap of a merged send */
|
|
1153
|
+
private readonly opSizes = new WeakMap<QueuedOperation, number>();
|
|
1154
|
+
/** The cap of ids of one send that an error of `isTooLarge` set, below `pushBatch.maxItems` (roadmap CLI-121) */
|
|
1155
|
+
private itemCap: number | undefined;
|
|
1076
1156
|
/** True when the queue store can differ from `offlineOps`: a failed write, or sent operations */
|
|
1077
1157
|
private storeDirty = false;
|
|
1078
1158
|
/** The calls of the queue store, one at a time */
|
|
@@ -1224,6 +1304,8 @@ export class HybridStorage<T> implements CollectionStorage<T> {
|
|
|
1224
1304
|
isUnavailable: options.isUnavailable ?? defaultIsUnavailable,
|
|
1225
1305
|
isRefusal: options.isRefusal ?? defaultIsRefusal,
|
|
1226
1306
|
isTooLarge: options.isTooLarge ?? defaultIsTooLarge,
|
|
1307
|
+
capacityOf: options.capacityOf ?? defaultCapacityOf,
|
|
1308
|
+
...(options.pushBatch !== undefined && { pushBatch: pushBatchOf(options.pushBatch) }),
|
|
1227
1309
|
...(options.onRefused !== undefined && { onRefused: options.onRefused }),
|
|
1228
1310
|
...(options.onDropped !== undefined && { onDropped: options.onDropped }),
|
|
1229
1311
|
};
|
|
@@ -3094,6 +3176,8 @@ export class HybridStorage<T> implements CollectionStorage<T> {
|
|
|
3094
3176
|
let split = false;
|
|
3095
3177
|
// The operations whose conflicts this push resolved once (roadmap CLI-16)
|
|
3096
3178
|
const resolved = new Set<QueuedOperation>();
|
|
3179
|
+
// The operations that go alone: a merged send of them failed (roadmap CLI-121)
|
|
3180
|
+
const alone = new Set<QueuedOperation>();
|
|
3097
3181
|
try {
|
|
3098
3182
|
while (this.offlineOps.length > 0) {
|
|
3099
3183
|
const op = this.offlineOps[0]!;
|
|
@@ -3102,6 +3186,51 @@ export class HybridStorage<T> implements CollectionStorage<T> {
|
|
|
3102
3186
|
await this.storeChain;
|
|
3103
3187
|
continue;
|
|
3104
3188
|
}
|
|
3189
|
+
const chunks = this.chunksOfHead(op);
|
|
3190
|
+
if (chunks.length > 1) {
|
|
3191
|
+
// A batch over the caps goes as batches within the caps (roadmap CLI-121)
|
|
3192
|
+
if (alone.has(op)) for (const chunk of chunks) alone.add(chunk);
|
|
3193
|
+
this.offlineOps.splice(0, 1, ...chunks);
|
|
3194
|
+
split = true;
|
|
3195
|
+
this.storeDirty = true;
|
|
3196
|
+
continue;
|
|
3197
|
+
}
|
|
3198
|
+
const run = this.pushRun(alone);
|
|
3199
|
+
if (run.length > 1) {
|
|
3200
|
+
this.sendingCount = run.length;
|
|
3201
|
+
try {
|
|
3202
|
+
for (const queued of run) this.echoSent(queued);
|
|
3203
|
+
await this.executeOperation(mergedOperation(run));
|
|
3204
|
+
} catch (error) {
|
|
3205
|
+
const conflicts = this.sendsBaseVersions() ? versionConflictsOf(error) : undefined;
|
|
3206
|
+
const refusal = this.refusalOf(error, conflicts);
|
|
3207
|
+
if (refusal === "too-large" && this.lowerItemCap(run.reduce((sum, queued) => sum + idsOf(queued).length, 0), error)) {
|
|
3208
|
+
// The same writes go again in smaller sends
|
|
3209
|
+
this.isOnline = true;
|
|
3210
|
+
continue;
|
|
3211
|
+
}
|
|
3212
|
+
if ((conflicts !== undefined && conflicts.length > 0) || refusal !== undefined) {
|
|
3213
|
+
// Each write of the run goes again alone, so the policy and the hooks get each write as without the merge
|
|
3214
|
+
this.isOnline = true;
|
|
3215
|
+
for (const queued of run) alone.add(queued);
|
|
3216
|
+
continue;
|
|
3217
|
+
}
|
|
3218
|
+
// The run and the later operations stay queued
|
|
3219
|
+
if (conflicts === undefined) this.isOnline = false;
|
|
3220
|
+
throw error;
|
|
3221
|
+
} finally {
|
|
3222
|
+
this.sendingCount = 0;
|
|
3223
|
+
}
|
|
3224
|
+
for (const queued of run) this.noteRemoteWrite(queued);
|
|
3225
|
+
// Remove the operations only after they reached the remote
|
|
3226
|
+
for (const queued of run) {
|
|
3227
|
+
if (this.offlineOps[0] !== queued) break;
|
|
3228
|
+
this.offlineOps.shift();
|
|
3229
|
+
sent++;
|
|
3230
|
+
this.storeDirty = true;
|
|
3231
|
+
}
|
|
3232
|
+
continue;
|
|
3233
|
+
}
|
|
3105
3234
|
try {
|
|
3106
3235
|
this.echoSent(op);
|
|
3107
3236
|
await this.executeOperation(op);
|
|
@@ -3121,13 +3250,18 @@ export class HybridStorage<T> implements CollectionStorage<T> {
|
|
|
3121
3250
|
}
|
|
3122
3251
|
continue;
|
|
3123
3252
|
}
|
|
3124
|
-
const
|
|
3125
|
-
|
|
3126
|
-
|
|
3253
|
+
const refusal = this.refusalOf(error, conflicts);
|
|
3254
|
+
if (refusal === "too-large" && this.lowerItemCap(idsOf(op).length, error)) {
|
|
3255
|
+
// The batch goes again in smaller batches, not as one write for each id (roadmap CLI-121)
|
|
3256
|
+
this.isOnline = true;
|
|
3257
|
+
continue;
|
|
3258
|
+
}
|
|
3259
|
+
if (refusal !== undefined) {
|
|
3127
3260
|
this.isOnline = true;
|
|
3128
3261
|
const singles = singlesOf(op);
|
|
3129
3262
|
if (singles.length > 1 && this.offlineOps[0] === op) {
|
|
3130
3263
|
// A batch goes again as one write for each id, so only the bad write leaves the queue (roadmap CLI-108)
|
|
3264
|
+
if (alone.has(op)) for (const single of singles) alone.add(single);
|
|
3131
3265
|
this.offlineOps.splice(0, 1, ...singles);
|
|
3132
3266
|
split = true;
|
|
3133
3267
|
this.storeDirty = true;
|
|
@@ -3139,7 +3273,7 @@ export class HybridStorage<T> implements CollectionStorage<T> {
|
|
|
3139
3273
|
sent++;
|
|
3140
3274
|
this.storeDirty = true;
|
|
3141
3275
|
}
|
|
3142
|
-
await this.refuseQueued(op, error,
|
|
3276
|
+
await this.refuseQueued(op, error, refusal);
|
|
3143
3277
|
continue;
|
|
3144
3278
|
}
|
|
3145
3279
|
// This operation and the later ones stay queued
|
|
@@ -3165,6 +3299,89 @@ export class HybridStorage<T> implements CollectionStorage<T> {
|
|
|
3165
3299
|
}
|
|
3166
3300
|
}
|
|
3167
3301
|
|
|
3302
|
+
/**
|
|
3303
|
+
* This method tells if the remote refused a write: `too-large`, `refused`, or undefined for another error. A conflict
|
|
3304
|
+
* and an error of the queue store are not a refusal.
|
|
3305
|
+
*/
|
|
3306
|
+
private refusalOf(error: unknown, conflicts: readonly VersionConflict[] | undefined): "too-large" | "refused" | undefined {
|
|
3307
|
+
if (conflicts !== undefined || error instanceof QueueStoreError) return undefined;
|
|
3308
|
+
if (this.options.isTooLarge(error)) return "too-large";
|
|
3309
|
+
return !this.options.isUnavailable(error) && this.options.isRefusal(error) ? "refused" : undefined;
|
|
3310
|
+
}
|
|
3311
|
+
|
|
3312
|
+
/**
|
|
3313
|
+
* This method gives the run of queued operations at the head of the queue that one send takes (roadmap CLI-121). The
|
|
3314
|
+
* run is the head operation alone when `pushBatch` is not set, or when the head cannot join a merged send.
|
|
3315
|
+
*/
|
|
3316
|
+
private pushRun(alone: ReadonlySet<QueuedOperation>): QueuedOperation[] {
|
|
3317
|
+
const head = this.offlineOps[0]!;
|
|
3318
|
+
const caps = this.options.pushBatch;
|
|
3319
|
+
const kind = mergeKind(head);
|
|
3320
|
+
if (caps === undefined || kind === undefined || alone.has(head) || !this.canJoinRun(head)) return [head];
|
|
3321
|
+
const run: QueuedOperation[] = [];
|
|
3322
|
+
const ids = new Set<string>();
|
|
3323
|
+
let items = 0;
|
|
3324
|
+
let bytes = 0;
|
|
3325
|
+
for (const op of this.offlineOps) {
|
|
3326
|
+
if (mergeKind(op) !== kind || alone.has(op) || this.unpersisted.has(op) || !this.canJoinRun(op)) break;
|
|
3327
|
+
const opIds = idsOf(op);
|
|
3328
|
+
// A second write of an id goes in a later send, so the order of the writes of the id stays
|
|
3329
|
+
if (opIds.some((id) => ids.has(id))) break;
|
|
3330
|
+
const size = this.sizeOf(op);
|
|
3331
|
+
if (run.length > 0 && (items + opIds.length > this.maxItemsOf(caps) || bytes + size > caps.maxBytes)) break;
|
|
3332
|
+
run.push(op);
|
|
3333
|
+
for (const id of opIds) ids.add(id);
|
|
3334
|
+
items += opIds.length;
|
|
3335
|
+
bytes += size;
|
|
3336
|
+
}
|
|
3337
|
+
return run;
|
|
3338
|
+
}
|
|
3339
|
+
|
|
3340
|
+
/** This method gives the batches within the caps of `pushBatch` of the head operation, or the head alone. */
|
|
3341
|
+
private chunksOfHead(op: QueuedOperation): QueuedOperation[] {
|
|
3342
|
+
const caps = this.options.pushBatch;
|
|
3343
|
+
if (caps === undefined || mergeKind(op) === undefined) return [op];
|
|
3344
|
+
const maxItems = this.maxItemsOf(caps);
|
|
3345
|
+
if (idsOf(op).length <= maxItems && this.sizeOf(op) <= caps.maxBytes) return [op];
|
|
3346
|
+
return chunksOf(op, maxItems, caps.maxBytes);
|
|
3347
|
+
}
|
|
3348
|
+
|
|
3349
|
+
/** This method gives the cap of ids of one send: `pushBatch.maxItems`, or the lower cap that an error of `isTooLarge` set. */
|
|
3350
|
+
private maxItemsOf(caps: { maxItems: number }): number {
|
|
3351
|
+
return this.itemCap === undefined ? caps.maxItems : Math.min(caps.maxItems, this.itemCap);
|
|
3352
|
+
}
|
|
3353
|
+
|
|
3354
|
+
/**
|
|
3355
|
+
* This method lowers the cap of ids of each later send after an error of `isTooLarge` for a send of `ids` ids (roadmap
|
|
3356
|
+
* CLI-121). With a capacity of `capacityOf`, the cap is ids × capacity / units, else half of the ids. It is false when
|
|
3357
|
+
* `pushBatch` is not set or the send had one id: then the write leaves the queue as before.
|
|
3358
|
+
*/
|
|
3359
|
+
private lowerItemCap(ids: number, error: unknown): boolean {
|
|
3360
|
+
if (this.options.pushBatch === undefined || ids <= 1) return false;
|
|
3361
|
+
const capacity = this.options.capacityOf(error);
|
|
3362
|
+
const next = capacity === undefined ? Math.floor(ids / 2) : Math.floor((ids * capacity.capacity) / capacity.units);
|
|
3363
|
+
// Each lower cap is smaller than the refused send, thus the push ends
|
|
3364
|
+
const cap = Math.max(1, Math.min(ids - 1, next));
|
|
3365
|
+
this.itemCap = this.itemCap === undefined ? cap : Math.min(this.itemCap, cap);
|
|
3366
|
+
return true;
|
|
3367
|
+
}
|
|
3368
|
+
|
|
3369
|
+
/** True when an operation can join a merged send. A delete of one id with a base version cannot: `deleteBatch` sends no base versions. */
|
|
3370
|
+
private canJoinRun(op: QueuedOperation): boolean {
|
|
3371
|
+
if (op.type !== "delete" || !this.sendsBaseVersions()) return true;
|
|
3372
|
+
return this.bases.get((op.data as { id: string }).id) === undefined;
|
|
3373
|
+
}
|
|
3374
|
+
|
|
3375
|
+
/** The length of the JSON text of the data of an operation. */
|
|
3376
|
+
private sizeOf(op: QueuedOperation): number {
|
|
3377
|
+
let size = this.opSizes.get(op);
|
|
3378
|
+
if (size === undefined) {
|
|
3379
|
+
size = JSON.stringify(op.data)?.length ?? 0;
|
|
3380
|
+
this.opSizes.set(op, size);
|
|
3381
|
+
}
|
|
3382
|
+
return size;
|
|
3383
|
+
}
|
|
3384
|
+
|
|
3168
3385
|
/**
|
|
3169
3386
|
* This method ends a queued write that the remote refused (roadmap O67). The local copy of its ids
|
|
3170
3387
|
* gets the remote values, and the hook `onRefused` gets the refusal. A refused clear asks for a
|
|
@@ -3576,8 +3793,8 @@ export class HybridStorage<T> implements CollectionStorage<T> {
|
|
|
3576
3793
|
const queued = this.offlineOps[index]!;
|
|
3577
3794
|
const ids = idsOf(queued);
|
|
3578
3795
|
if (!ids.includes(id) && !ids.includes("*")) continue;
|
|
3579
|
-
// pushQueue can be sending the first
|
|
3580
|
-
const sending = index
|
|
3796
|
+
// pushQueue can be sending the first operations at this time: do not change them
|
|
3797
|
+
const sending = index < Math.max(1, this.sendingCount) && this.pushing;
|
|
3581
3798
|
return !sending && (queued.type === "set" || queued.type === "delete") ? index : -1;
|
|
3582
3799
|
}
|
|
3583
3800
|
return -1;
|
package/src/storage/index.ts
CHANGED
package/src/storage/queue.ts
CHANGED
|
@@ -143,6 +143,44 @@ export function singlesOf(op: QueuedOperation): QueuedOperation[] {
|
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
+
/**
|
|
147
|
+
* This function cuts a batch into batches of consecutive ids within the caps, in its order, with the base version of
|
|
148
|
+
* each id (roadmap CLI-121). The size of an entry is the length of its JSON text. An entry over `maxBytes` goes in a
|
|
149
|
+
* chunk alone. A set, a delete and a clear give an array of the operation itself.
|
|
150
|
+
*/
|
|
151
|
+
export function chunksOf(op: QueuedOperation, maxItems: number, maxBytes: number): QueuedOperation[] {
|
|
152
|
+
if (op.type !== "setBatch" && op.type !== "deleteBatch") return [op];
|
|
153
|
+
const data = op.data as { ids?: string[]; items?: Array<[string, unknown]> };
|
|
154
|
+
const entries: Array<string | [string, unknown]> = op.type === "setBatch" ? (data.items ?? []) : (data.ids ?? []);
|
|
155
|
+
const groups: Array<Array<string | [string, unknown]>> = [];
|
|
156
|
+
let group: Array<string | [string, unknown]> = [];
|
|
157
|
+
let bytes = 0;
|
|
158
|
+
for (const entry of entries) {
|
|
159
|
+
const size = JSON.stringify(entry)?.length ?? 0;
|
|
160
|
+
if (group.length > 0 && (group.length + 1 > maxItems || bytes + size > maxBytes)) {
|
|
161
|
+
groups.push(group);
|
|
162
|
+
group = [];
|
|
163
|
+
bytes = 0;
|
|
164
|
+
}
|
|
165
|
+
group.push(entry);
|
|
166
|
+
bytes += size;
|
|
167
|
+
}
|
|
168
|
+
if (group.length > 0) groups.push(group);
|
|
169
|
+
if (groups.length <= 1) return [op];
|
|
170
|
+
return groups.map((chunk) => {
|
|
171
|
+
const ids = new Set(chunk.map((entry) => (typeof entry === "string" ? entry : entry[0])));
|
|
172
|
+
const base = op.base?.filter(([id]) => ids.has(id));
|
|
173
|
+
const baseValues = op.baseValues?.filter(([id]) => ids.has(id));
|
|
174
|
+
return {
|
|
175
|
+
type: op.type,
|
|
176
|
+
data: op.type === "setBatch" ? { items: chunk as Array<[string, unknown]> } : { ids: chunk as string[] },
|
|
177
|
+
timestamp: op.timestamp,
|
|
178
|
+
...(base !== undefined && base.length > 0 && { base }),
|
|
179
|
+
...(baseValues !== undefined && baseValues.length > 0 && { baseValues }),
|
|
180
|
+
};
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
146
184
|
/** True when a value has the shape of a queued operation. A loaded file can hold anything. */
|
|
147
185
|
export function isQueuedOperation(value: unknown): value is QueuedOperation {
|
|
148
186
|
if (typeof value !== "object" || value === null) return false;
|