@travetto/model-redis 8.0.0-alpha.11 → 8.0.0-alpha.13
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/package.json +5 -5
- package/src/service.ts +28 -31
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/model-redis",
|
|
3
|
-
"version": "8.0.0-alpha.
|
|
3
|
+
"version": "8.0.0-alpha.13",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Redis backing for the travetto model module.",
|
|
6
6
|
"keywords": [
|
|
@@ -27,12 +27,12 @@
|
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@redis/client": "^5.11.0",
|
|
30
|
-
"@travetto/config": "^8.0.0-alpha.
|
|
31
|
-
"@travetto/model": "^8.0.0-alpha.
|
|
32
|
-
"@travetto/model-indexed": "^8.0.0-alpha.
|
|
30
|
+
"@travetto/config": "^8.0.0-alpha.12",
|
|
31
|
+
"@travetto/model": "^8.0.0-alpha.12",
|
|
32
|
+
"@travetto/model-indexed": "^8.0.0-alpha.13"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
|
-
"@travetto/cli": "^8.0.0-alpha.
|
|
35
|
+
"@travetto/cli": "^8.0.0-alpha.17"
|
|
36
36
|
},
|
|
37
37
|
"peerDependenciesMeta": {
|
|
38
38
|
"@travetto/cli": {
|
package/src/service.ts
CHANGED
|
@@ -4,10 +4,11 @@ import { castTo, JSONUtil, ShutdownManager, type Class } from '@travetto/runtime
|
|
|
4
4
|
import {
|
|
5
5
|
type ModelCrudSupport, type ModelExpirySupport, ModelRegistryIndex, type ModelType, type ModelStorageSupport, NotFoundError,
|
|
6
6
|
ExistsError, type OptionalId, ModelCrudUtil, ModelExpiryUtil, ModelStorageUtil,
|
|
7
|
+
type ModelListOptions,
|
|
7
8
|
} from '@travetto/model';
|
|
8
9
|
import {
|
|
9
|
-
type ModelIndexedSupport, type KeyedIndexSelection, type KeyedIndexBody, type
|
|
10
|
-
type SingleItemIndex, type SortedIndexSelection, type
|
|
10
|
+
type ModelIndexedSupport, type KeyedIndexSelection, type KeyedIndexBody, type ModelPageOptions, ModelIndexedUtil,
|
|
11
|
+
type SingleItemIndex, type SortedIndexSelection, type ModelPageResult, type SortedIndex, isModelIndexedIndex,
|
|
11
12
|
type FullKeyedIndexWithPartialBody, type FullKeyedIndexBody, ModelIndexedComputedIndex,
|
|
12
13
|
} from '@travetto/model-indexed';
|
|
13
14
|
|
|
@@ -69,18 +70,23 @@ export class RedisModelService implements ModelCrudSupport, ModelExpirySupport,
|
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
async * #streamValues(
|
|
72
|
-
operation: ScanOp,
|
|
73
|
+
operation: ScanOp,
|
|
74
|
+
search: RedisScan,
|
|
75
|
+
options?: ModelPageOptions & ModelListOptions
|
|
73
76
|
): AsyncIterable<ScanState> {
|
|
74
77
|
const limit = options?.limit ?? Number.MAX_SAFE_INTEGER;
|
|
75
78
|
let matched: ScanState = { cursor: options?.offset, ids: [] };
|
|
76
79
|
let produced = 0;
|
|
80
|
+
const batchSize = options?.batchSizeHint ?? 100;
|
|
77
81
|
|
|
78
82
|
do {
|
|
79
83
|
const remaining = limit - produced;
|
|
80
|
-
matched = await this.#scan(operation, matched.cursor!, search, Math.min(remaining,
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
+
matched = await this.#scan(operation, matched.cursor!, search, Math.min(remaining, batchSize));
|
|
85
|
+
if (matched.ids.length) {
|
|
86
|
+
yield matched;
|
|
87
|
+
produced += matched.ids.length;
|
|
88
|
+
}
|
|
89
|
+
} while (matched.cursor && produced < limit && !(options?.abort?.aborted));
|
|
84
90
|
}
|
|
85
91
|
|
|
86
92
|
#scanIndex<
|
|
@@ -91,7 +97,7 @@ export class RedisModelService implements ModelCrudSupport, ModelExpirySupport,
|
|
|
91
97
|
cls: Class<T>,
|
|
92
98
|
idx: SortedIndex<T, K, S>,
|
|
93
99
|
body: KeyedIndexBody<T, K>,
|
|
94
|
-
options?:
|
|
100
|
+
options?: ModelPageOptions
|
|
95
101
|
): AsyncIterable<ScanState> {
|
|
96
102
|
ModelCrudUtil.ensureNotSubType(cls);
|
|
97
103
|
const computed = ModelIndexedComputedIndex.get(idx, body).validate();
|
|
@@ -104,21 +110,13 @@ export class RedisModelService implements ModelCrudSupport, ModelExpirySupport,
|
|
|
104
110
|
}
|
|
105
111
|
}
|
|
106
112
|
|
|
107
|
-
async
|
|
113
|
+
async #getBodies<T extends ModelType>(cls: Class<T>, ids: string[], transform: (id: string) => string): Promise<T[]> {
|
|
108
114
|
if (ids.length === 0) {
|
|
109
|
-
return;
|
|
115
|
+
return [];
|
|
110
116
|
}
|
|
111
117
|
const bodies = (await this.client.mGet(ids.map(transform)))
|
|
112
118
|
.filter((result): result is string => !!result);
|
|
113
|
-
|
|
114
|
-
try {
|
|
115
|
-
yield await ModelCrudUtil.load(cls, body);
|
|
116
|
-
} catch (error) {
|
|
117
|
-
if (!(error instanceof NotFoundError)) {
|
|
118
|
-
throw error;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
119
|
+
return ModelCrudUtil.filterOutNotFound(bodies.map(body => ModelCrudUtil.load(cls, body)));
|
|
122
120
|
}
|
|
123
121
|
|
|
124
122
|
#removeIndices<T extends ModelType>(cls: Class, item: T, multi: RedisMulti): void {
|
|
@@ -316,9 +314,9 @@ export class RedisModelService implements ModelCrudSupport, ModelExpirySupport,
|
|
|
316
314
|
await this.#store(cls, where, 'delete');
|
|
317
315
|
}
|
|
318
316
|
|
|
319
|
-
async * list<T extends ModelType>(cls: Class<T
|
|
320
|
-
for await (const { ids } of this.#streamValues('scan', { match: `${this.#resolveKey(cls)}:*` },
|
|
321
|
-
yield
|
|
317
|
+
async * list<T extends ModelType>(cls: Class<T>, options?: ModelListOptions): AsyncIterable<T[]> {
|
|
318
|
+
for await (const { ids } of this.#streamValues('scan', { match: `${this.#resolveKey(cls)}:*` }, options)) {
|
|
319
|
+
yield await this.#getBodies(cls, ids, id => id);
|
|
322
320
|
}
|
|
323
321
|
}
|
|
324
322
|
|
|
@@ -404,14 +402,12 @@ export class RedisModelService implements ModelCrudSupport, ModelExpirySupport,
|
|
|
404
402
|
cls: Class<T>,
|
|
405
403
|
idx: SortedIndex<T, K, S>,
|
|
406
404
|
body: KeyedIndexBody<T, K>,
|
|
407
|
-
options?:
|
|
408
|
-
): Promise<
|
|
405
|
+
options?: ModelPageOptions
|
|
406
|
+
): Promise<ModelPageResult<T>> {
|
|
409
407
|
const items: T[] = [];
|
|
410
408
|
let lastCursor: string | undefined;
|
|
411
409
|
for await (const { ids, cursor } of this.#scanIndex(cls, idx, body, { limit: 100, ...options })) {
|
|
412
|
-
items.push(
|
|
413
|
-
...await Array.fromAsync(this.#getBodies(cls, ids, id => this.#resolveKey(cls, id)))
|
|
414
|
-
);
|
|
410
|
+
items.push(...await this.#getBodies(cls, ids, id => this.#resolveKey(cls, id)));
|
|
415
411
|
lastCursor = cursor;
|
|
416
412
|
}
|
|
417
413
|
return { items, nextOffset: lastCursor };
|
|
@@ -424,10 +420,11 @@ export class RedisModelService implements ModelCrudSupport, ModelExpirySupport,
|
|
|
424
420
|
>(
|
|
425
421
|
cls: Class<T>,
|
|
426
422
|
idx: SortedIndex<T, K, S>,
|
|
427
|
-
body: KeyedIndexBody<T, K
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
423
|
+
body: KeyedIndexBody<T, K>,
|
|
424
|
+
options?: ModelListOptions
|
|
425
|
+
): AsyncIterable<T[]> {
|
|
426
|
+
for await (const { ids } of this.#scanIndex(cls, idx, body, options)) {
|
|
427
|
+
yield await this.#getBodies(cls, ids, id => this.#resolveKey(cls, id));
|
|
431
428
|
}
|
|
432
429
|
}
|
|
433
430
|
}
|