@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.
Files changed (2) hide show
  1. package/package.json +5 -5
  2. 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.11",
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.10",
31
- "@travetto/model": "^8.0.0-alpha.10",
32
- "@travetto/model-indexed": "^8.0.0-alpha.11"
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.15"
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 ListPageOptions, ModelIndexedUtil,
10
- type SingleItemIndex, type SortedIndexSelection, type ListPageResult, type SortedIndex, isModelIndexedIndex,
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, search: RedisScan, options?: ListPageOptions, count = 10
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, count));
81
- yield matched;
82
- produced += matched.ids.length;
83
- } while (matched.cursor && produced < limit);
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?: ListPageOptions
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 * #getBodies<T extends ModelType>(cls: Class<T>, ids: string[], transform: (id: string) => string): AsyncIterable<T> {
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
- for (const body of bodies) {
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>): AsyncIterable<T> {
320
- for await (const { ids } of this.#streamValues('scan', { match: `${this.#resolveKey(cls)}:*` }, { limit: Number.MAX_SAFE_INTEGER })) {
321
- yield* this.#getBodies(cls, ids, id => id);
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?: ListPageOptions
408
- ): Promise<ListPageResult<T>> {
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
- ): AsyncIterable<T> {
429
- for await (const { ids } of this.#scanIndex(cls, idx, body, { limit: Number.MAX_SAFE_INTEGER })) {
430
- yield* await Array.fromAsync(this.#getBodies(cls, ids, id => this.#resolveKey(cls, id)));
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
  }