@travetto/model-memory 8.0.0-alpha.10 → 8.0.0-alpha.12
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/README.md +1 -1
- package/package.json +8 -8
- package/src/service.ts +76 -28
package/README.md
CHANGED
|
@@ -17,4 +17,4 @@ This module provides a memory-based implementation for the [Data Modeling Suppor
|
|
|
17
17
|
* [CRUD](https://github.com/travetto/travetto/tree/main/module/model/src/types/crud.ts#L11)
|
|
18
18
|
* [Expiry](https://github.com/travetto/travetto/tree/main/module/model/src/types/expiry.ts#L10)
|
|
19
19
|
* [Blob](https://github.com/travetto/travetto/tree/main/module/model/src/types/blob.ts#L8)
|
|
20
|
-
* [Indexed](https://github.com/travetto/travetto/tree/main/module/model-indexed/src/types/service.ts#
|
|
20
|
+
* [Indexed](https://github.com/travetto/travetto/tree/main/module/model-indexed/src/types/service.ts#L15)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/model-memory",
|
|
3
|
-
"version": "8.0.0-alpha.
|
|
3
|
+
"version": "8.0.0-alpha.12",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Memory backing for the travetto model module.",
|
|
6
6
|
"keywords": [
|
|
@@ -26,15 +26,15 @@
|
|
|
26
26
|
"directory": "module/model-memory"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@travetto/config": "^8.0.0-alpha.
|
|
30
|
-
"@travetto/di": "^8.0.0-alpha.
|
|
31
|
-
"@travetto/model": "^8.0.0-alpha.
|
|
32
|
-
"@travetto/model-indexed": "^8.0.0-alpha.
|
|
33
|
-
"@travetto/schema": "^8.0.0-alpha.
|
|
29
|
+
"@travetto/config": "^8.0.0-alpha.11",
|
|
30
|
+
"@travetto/di": "^8.0.0-alpha.11",
|
|
31
|
+
"@travetto/model": "^8.0.0-alpha.11",
|
|
32
|
+
"@travetto/model-indexed": "^8.0.0-alpha.12",
|
|
33
|
+
"@travetto/schema": "^8.0.0-alpha.11"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
|
-
"@travetto/cli": "^8.0.0-alpha.
|
|
37
|
-
"@travetto/test": "^8.0.0-alpha.
|
|
36
|
+
"@travetto/cli": "^8.0.0-alpha.16",
|
|
37
|
+
"@travetto/test": "^8.0.0-alpha.11"
|
|
38
38
|
},
|
|
39
39
|
"peerDependenciesMeta": {
|
|
40
40
|
"@travetto/cli": {
|
package/src/service.ts
CHANGED
|
@@ -8,10 +8,11 @@ import {
|
|
|
8
8
|
type ModelType, type ModelCrudSupport, type ModelExpirySupport, type ModelStorageSupport, ModelRegistryIndex,
|
|
9
9
|
NotFoundError, ExistsError, type OptionalId, type ModelBlobSupport, ModelCrudUtil, ModelExpiryUtil, ModelStorageUtil,
|
|
10
10
|
IndexNotSupported,
|
|
11
|
+
type ModelListOptions,
|
|
11
12
|
} from '@travetto/model';
|
|
12
13
|
import {
|
|
13
|
-
type ModelIndexedSupport, type KeyedIndexSelection, type KeyedIndexBody, type
|
|
14
|
-
type SingleItemIndex, type SortedIndexSelection, type
|
|
14
|
+
type ModelIndexedSupport, type KeyedIndexSelection, type KeyedIndexBody, type ModelPageOptions, ModelIndexedUtil,
|
|
15
|
+
type SingleItemIndex, type SortedIndexSelection, type ModelPageResult, type SortedIndex,
|
|
15
16
|
type AllIndexes, isModelIndexedIndex, type FullKeyedIndexBody, type FullKeyedIndexWithPartialBody, ModelIndexedComputedIndex,
|
|
16
17
|
} from '@travetto/model-indexed';
|
|
17
18
|
|
|
@@ -150,10 +151,18 @@ export class MemoryModelService implements
|
|
|
150
151
|
const index = this.#indices[idx.type].get(indexName(cls, idx))?.get(computed.getKey());
|
|
151
152
|
let id: string | undefined;
|
|
152
153
|
if (index) {
|
|
153
|
-
if (
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
154
|
+
if (computed.idPart) {
|
|
155
|
+
if (index.has(computed.idPart.value)) {
|
|
156
|
+
id = computed.idPart.value;
|
|
157
|
+
} else {
|
|
158
|
+
throw new NotFoundError(cls, computed.getKey({ sort: true }));
|
|
159
|
+
}
|
|
160
|
+
} else {
|
|
161
|
+
if (index instanceof Map) {
|
|
162
|
+
id = getFirstId(index, computed.getSort()); // Grab first id
|
|
163
|
+
} else if (index instanceof Set) {
|
|
164
|
+
id = getFirstId(index); // Grab first id
|
|
165
|
+
}
|
|
157
166
|
}
|
|
158
167
|
}
|
|
159
168
|
if (id) {
|
|
@@ -162,11 +171,39 @@ export class MemoryModelService implements
|
|
|
162
171
|
throw new NotFoundError(cls, computed.getKey({ sort: true }));
|
|
163
172
|
}
|
|
164
173
|
|
|
165
|
-
#
|
|
174
|
+
async * #iterateIds<T extends ModelType>(
|
|
175
|
+
ids: string[],
|
|
176
|
+
options?: ModelListOptions & ModelPageOptions<number>
|
|
177
|
+
|
|
178
|
+
): AsyncIterable<string[]> {
|
|
179
|
+
let offset = options && 'offset' in options ? options.offset ?? 0 : 0;
|
|
180
|
+
const batchSize = options?.batchSizeHint ?? 100;
|
|
181
|
+
let produced = 0;
|
|
182
|
+
const maxCount = options?.limit ?? Number.MAX_SAFE_INTEGER;
|
|
183
|
+
while (offset < ids.length && produced < maxCount) {
|
|
184
|
+
if (options?.abort?.aborted) {
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
const end = Math.min(offset + batchSize, ids.length, maxCount - produced + offset);
|
|
188
|
+
const batch = ids.slice(offset, end);
|
|
189
|
+
if (batch.length) {
|
|
190
|
+
yield batch;
|
|
191
|
+
}
|
|
192
|
+
offset += batchSize;
|
|
193
|
+
produced += batch.length;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
async * #getIndexIds<
|
|
166
198
|
T extends ModelType,
|
|
167
199
|
K extends KeyedIndexSelection<T>,
|
|
168
200
|
S extends SortedIndexSelection<T>
|
|
169
|
-
>(
|
|
201
|
+
>(
|
|
202
|
+
cls: Class<T>,
|
|
203
|
+
idx: AllIndexes<T, K, S>,
|
|
204
|
+
body: KeyedIndexBody<T, K>,
|
|
205
|
+
options?: ModelListOptions & ModelPageOptions<number>
|
|
206
|
+
): AsyncIterable<string[]> {
|
|
170
207
|
const computed = ModelIndexedComputedIndex.get(idx, body).validate();
|
|
171
208
|
if (!isModelIndexedIndex(idx)) {
|
|
172
209
|
throw new IndexNotSupported(cls, idx, 'Only ModelIndexed indices can be used with MemoryModelService');
|
|
@@ -174,13 +211,15 @@ export class MemoryModelService implements
|
|
|
174
211
|
|
|
175
212
|
const base = this.#indices[idx.type].get(indexName(cls, idx));
|
|
176
213
|
const index = base?.get(computed.getKey());
|
|
214
|
+
let ids: string[];
|
|
177
215
|
if (!index) {
|
|
178
|
-
|
|
216
|
+
ids = [];
|
|
179
217
|
} else if (index instanceof Map) {
|
|
180
|
-
|
|
218
|
+
ids = [...index.entries()].toSorted((a, b) => a[1] - b[1]).map(([id,]) => id);
|
|
181
219
|
} else {
|
|
182
|
-
|
|
220
|
+
ids = [...index];
|
|
183
221
|
}
|
|
222
|
+
yield* this.#iterateIds(ids, options);
|
|
184
223
|
}
|
|
185
224
|
|
|
186
225
|
@PostConstruct()
|
|
@@ -253,15 +292,9 @@ export class MemoryModelService implements
|
|
|
253
292
|
await this.#persist(cls, where, 'remove');
|
|
254
293
|
}
|
|
255
294
|
|
|
256
|
-
async * list<T extends ModelType>(cls: Class<T
|
|
257
|
-
for (const
|
|
258
|
-
|
|
259
|
-
yield await this.get(cls, id);
|
|
260
|
-
} catch (error) {
|
|
261
|
-
if (!(error instanceof NotFoundError)) {
|
|
262
|
-
throw error;
|
|
263
|
-
}
|
|
264
|
-
}
|
|
295
|
+
async * list<T extends ModelType>(cls: Class<T>, options?: ModelListOptions): AsyncIterable<T[]> {
|
|
296
|
+
for await (const batch of this.#iterateIds([...this.#getStore(cls).keys()], options)) {
|
|
297
|
+
yield ModelCrudUtil.filterOutNotFound(batch.map(id => this.get(cls, id)));
|
|
265
298
|
}
|
|
266
299
|
}
|
|
267
300
|
|
|
@@ -400,7 +433,7 @@ export class MemoryModelService implements
|
|
|
400
433
|
return this.update(cls, item);
|
|
401
434
|
}
|
|
402
435
|
|
|
403
|
-
async
|
|
436
|
+
async pageByIndex<
|
|
404
437
|
T extends ModelType,
|
|
405
438
|
K extends KeyedIndexSelection<T>,
|
|
406
439
|
S extends SortedIndexSelection<T>
|
|
@@ -408,16 +441,31 @@ export class MemoryModelService implements
|
|
|
408
441
|
cls: Class<T>,
|
|
409
442
|
idx: SortedIndex<T, K, S>,
|
|
410
443
|
body: KeyedIndexBody<T, K>,
|
|
411
|
-
options?:
|
|
412
|
-
): Promise<
|
|
413
|
-
const ids = this.#getIndexIds(cls, idx, body);
|
|
444
|
+
options?: ModelPageOptions
|
|
445
|
+
): Promise<ModelPageResult<T>> {
|
|
414
446
|
const offset = options?.offset ? JSONUtil.fromBase64<number>(options.offset) : 0;
|
|
415
|
-
|
|
447
|
+
let produced = 0;
|
|
416
448
|
|
|
417
449
|
const items: T[] = [];
|
|
418
|
-
for (const
|
|
419
|
-
|
|
450
|
+
for await (const batch of this.#getIndexIds(cls, idx, body, { limit: 100, ...options, offset })) {
|
|
451
|
+
produced += batch.length;
|
|
452
|
+
items.push(...await ModelCrudUtil.filterOutNotFound(batch.map(id => this.get(cls, id))));
|
|
453
|
+
}
|
|
454
|
+
return { items, nextOffset: items.length ? JSONUtil.toBase64(offset + produced) : undefined };
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
async * listByIndex<
|
|
458
|
+
T extends ModelType,
|
|
459
|
+
K extends KeyedIndexSelection<T>,
|
|
460
|
+
S extends SortedIndexSelection<T>
|
|
461
|
+
>(
|
|
462
|
+
cls: Class<T>,
|
|
463
|
+
idx: SortedIndex<T, K, S>,
|
|
464
|
+
body: KeyedIndexBody<T, K>,
|
|
465
|
+
options?: ModelListOptions
|
|
466
|
+
): AsyncIterable<T[]> {
|
|
467
|
+
for await (const batch of this.#getIndexIds(cls, idx, body, options)) {
|
|
468
|
+
yield ModelCrudUtil.filterOutNotFound(batch.map(id => this.get(cls, id)));
|
|
420
469
|
}
|
|
421
|
-
return { items, nextOffset: items.length ? JSONUtil.toBase64(offset + items.length) : undefined };
|
|
422
470
|
}
|
|
423
471
|
}
|