@travetto/model-redis 7.0.0-rc.1 → 7.0.0-rc.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/README.md +3 -7
- package/package.json +4 -4
- package/src/config.ts +2 -6
- package/src/service.ts +33 -33
package/README.md
CHANGED
|
@@ -31,8 +31,8 @@ export class Init {
|
|
|
31
31
|
@InjectableFactory({
|
|
32
32
|
primary: true
|
|
33
33
|
})
|
|
34
|
-
static getModelSource(
|
|
35
|
-
return new RedisModelService(
|
|
34
|
+
static getModelSource(config: RedisModelConfig) {
|
|
35
|
+
return new RedisModelService(config);
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
```
|
|
@@ -45,11 +45,7 @@ where the [RedisModelConfig](https://github.com/travetto/travetto/tree/main/modu
|
|
|
45
45
|
export class RedisModelConfig {
|
|
46
46
|
client: redis.RedisClientOptions = {};
|
|
47
47
|
namespace?: string;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
postConstruct(): void {
|
|
51
|
-
|
|
52
|
-
}
|
|
48
|
+
modifyStorage?: boolean;
|
|
53
49
|
}
|
|
54
50
|
```
|
|
55
51
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/model-redis",
|
|
3
|
-
"version": "7.0.0-rc.
|
|
3
|
+
"version": "7.0.0-rc.3",
|
|
4
4
|
"description": "Redis backing for the travetto model module.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@redis/client": "^5.10.0",
|
|
29
|
-
"@travetto/cli": "^7.0.0-rc.
|
|
30
|
-
"@travetto/config": "^7.0.0-rc.
|
|
31
|
-
"@travetto/model": "^7.0.0-rc.
|
|
29
|
+
"@travetto/cli": "^7.0.0-rc.3",
|
|
30
|
+
"@travetto/config": "^7.0.0-rc.3",
|
|
31
|
+
"@travetto/model": "^7.0.0-rc.3"
|
|
32
32
|
},
|
|
33
33
|
"travetto": {
|
|
34
34
|
"displayName": "Redis Model Support"
|
package/src/config.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type redis from 'redis';
|
|
1
|
+
import type redis from '@redis/client';
|
|
2
2
|
|
|
3
3
|
import { Config } from '@travetto/config';
|
|
4
4
|
|
|
@@ -6,9 +6,5 @@ import { Config } from '@travetto/config';
|
|
|
6
6
|
export class RedisModelConfig {
|
|
7
7
|
client: redis.RedisClientOptions = {};
|
|
8
8
|
namespace?: string;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
postConstruct(): void {
|
|
12
|
-
|
|
13
|
-
}
|
|
9
|
+
modifyStorage?: boolean;
|
|
14
10
|
}
|
package/src/service.ts
CHANGED
|
@@ -40,8 +40,8 @@ export class RedisModelService implements ModelCrudSupport, ModelExpirySupport,
|
|
|
40
40
|
return key;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
async * #streamValues(
|
|
44
|
-
let
|
|
43
|
+
async * #streamValues(operation: 'scan' | 'sScan' | 'zScan', search: RedisScan, count = 100): AsyncIterable<string[]> {
|
|
44
|
+
let previousCursor = '0';
|
|
45
45
|
let done = false;
|
|
46
46
|
|
|
47
47
|
const flags = { COUNT: count, ...('match' in search ? { MATCH: search.match } : {}) };
|
|
@@ -49,14 +49,14 @@ export class RedisModelService implements ModelCrudSupport, ModelExpirySupport,
|
|
|
49
49
|
|
|
50
50
|
while (!done) {
|
|
51
51
|
const [cursor, results] = await (
|
|
52
|
-
|
|
53
|
-
this.client.scan(
|
|
54
|
-
|
|
55
|
-
this.client.sScan(key,
|
|
56
|
-
this.client.zScan(key,
|
|
52
|
+
operation === 'scan' ?
|
|
53
|
+
this.client.scan(previousCursor, flags).then(result => [result.cursor, result.keys] as const) :
|
|
54
|
+
operation === 'sScan' ?
|
|
55
|
+
this.client.sScan(key, previousCursor, flags).then(result => [result.cursor, result.members] as const) :
|
|
56
|
+
this.client.zScan(key, previousCursor, flags).then(result => [result.cursor, result.members.map(item => item.value)] as const)
|
|
57
57
|
);
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
previousCursor = cursor;
|
|
60
60
|
|
|
61
61
|
yield results;
|
|
62
62
|
|
|
@@ -149,17 +149,17 @@ export class RedisModelService implements ModelCrudSupport, ModelExpirySupport,
|
|
|
149
149
|
async #getIdByIndex<T extends ModelType>(cls: Class<T>, idx: string, body: DeepPartial<T>): Promise<string> {
|
|
150
150
|
ModelCrudUtil.ensureNotSubType(cls);
|
|
151
151
|
|
|
152
|
-
const
|
|
153
|
-
const { key, sort } = ModelIndexedUtil.computeIndexKey(cls,
|
|
154
|
-
const fullKey = this.#resolveKey(cls,
|
|
152
|
+
const idxConfig = ModelRegistryIndex.getIndex(cls, idx, ['sorted', 'unsorted']);
|
|
153
|
+
const { key, sort } = ModelIndexedUtil.computeIndexKey(cls, idxConfig, body);
|
|
154
|
+
const fullKey = this.#resolveKey(cls, idxConfig.name, key);
|
|
155
155
|
let id: string | undefined;
|
|
156
|
-
if (
|
|
156
|
+
if (idxConfig.type === 'unsorted') {
|
|
157
157
|
id = (await this.client.sRandMember(fullKey))!;
|
|
158
158
|
} else {
|
|
159
|
-
const
|
|
159
|
+
const result = await this.client.zRangeByScore(
|
|
160
160
|
fullKey, +sort!, +sort!
|
|
161
161
|
);
|
|
162
|
-
id =
|
|
162
|
+
id = result[0];
|
|
163
163
|
}
|
|
164
164
|
if (id) {
|
|
165
165
|
return id;
|
|
@@ -170,13 +170,13 @@ export class RedisModelService implements ModelCrudSupport, ModelExpirySupport,
|
|
|
170
170
|
async postConstruct(): Promise<void> {
|
|
171
171
|
this.client = createClient(this.config.client);
|
|
172
172
|
await this.client.connect();
|
|
173
|
-
await ModelStorageUtil.
|
|
173
|
+
await ModelStorageUtil.storageInitialization(this);
|
|
174
174
|
ShutdownManager.onGracefulShutdown(() => this.client.destroy());
|
|
175
|
-
for (const
|
|
176
|
-
for (const idx of ModelRegistryIndex.getConfig(
|
|
175
|
+
for (const cls of ModelRegistryIndex.getClasses()) {
|
|
176
|
+
for (const idx of ModelRegistryIndex.getConfig(cls).indices ?? []) {
|
|
177
177
|
switch (idx.type) {
|
|
178
178
|
case 'unique': {
|
|
179
|
-
console.error('Unique indices are not supported in redis for', { cls:
|
|
179
|
+
console.error('Unique indices are not supported in redis for', { cls: cls.Ⲑid, idx: idx.name });
|
|
180
180
|
break;
|
|
181
181
|
}
|
|
182
182
|
}
|
|
@@ -185,10 +185,10 @@ export class RedisModelService implements ModelCrudSupport, ModelExpirySupport,
|
|
|
185
185
|
}
|
|
186
186
|
|
|
187
187
|
async has<T extends ModelType>(cls: Class<T>, id: string, error?: 'notfound' | 'exists'): Promise<void> {
|
|
188
|
-
const
|
|
189
|
-
if (
|
|
188
|
+
const result = await this.client.exists(this.#resolveKey(cls, id));
|
|
189
|
+
if (result === 0 && error === 'notfound') {
|
|
190
190
|
throw new NotFoundError(cls, id);
|
|
191
|
-
} else if (
|
|
191
|
+
} else if (result === 1 && error === 'exists') {
|
|
192
192
|
throw new ExistsError(cls, id);
|
|
193
193
|
}
|
|
194
194
|
}
|
|
@@ -248,14 +248,14 @@ export class RedisModelService implements ModelCrudSupport, ModelExpirySupport,
|
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
const bodies = (await this.client.mGet(ids))
|
|
251
|
-
.filter((
|
|
251
|
+
.filter((result): result is string => !!result);
|
|
252
252
|
|
|
253
253
|
for (const body of bodies) {
|
|
254
254
|
try {
|
|
255
255
|
yield await ModelCrudUtil.load(cls, body);
|
|
256
|
-
} catch (
|
|
257
|
-
if (!(
|
|
258
|
-
throw
|
|
256
|
+
} catch (error) {
|
|
257
|
+
if (!(error instanceof NotFoundError)) {
|
|
258
|
+
throw error;
|
|
259
259
|
}
|
|
260
260
|
}
|
|
261
261
|
}
|
|
@@ -309,14 +309,14 @@ export class RedisModelService implements ModelCrudSupport, ModelExpirySupport,
|
|
|
309
309
|
async * listByIndex<T extends ModelType>(cls: Class<T>, idx: string, body?: DeepPartial<T>): AsyncIterable<T> {
|
|
310
310
|
ModelCrudUtil.ensureNotSubType(cls);
|
|
311
311
|
|
|
312
|
-
const
|
|
312
|
+
const idxConfig = ModelRegistryIndex.getIndex(cls, idx, ['sorted', 'unsorted']);
|
|
313
313
|
|
|
314
314
|
let stream: AsyncIterable<string[]>;
|
|
315
315
|
|
|
316
|
-
const { key } = ModelIndexedUtil.computeIndexKey(cls,
|
|
316
|
+
const { key } = ModelIndexedUtil.computeIndexKey(cls, idxConfig, body, { emptySortValue: null });
|
|
317
317
|
const fullKey = this.#resolveKey(cls, idx, key);
|
|
318
318
|
|
|
319
|
-
if (
|
|
319
|
+
if (idxConfig.type === 'unsorted') {
|
|
320
320
|
stream = this.#streamValues('sScan', { key: fullKey });
|
|
321
321
|
} else {
|
|
322
322
|
stream = this.#streamValues('zScan', { key: fullKey });
|
|
@@ -328,16 +328,16 @@ export class RedisModelService implements ModelCrudSupport, ModelExpirySupport,
|
|
|
328
328
|
}
|
|
329
329
|
|
|
330
330
|
const bodies = (await this.client.mGet(
|
|
331
|
-
ids.map(
|
|
331
|
+
ids.map(id => this.#resolveKey(cls, id))
|
|
332
332
|
))
|
|
333
|
-
.filter((
|
|
333
|
+
.filter((result): result is string => !!result);
|
|
334
334
|
|
|
335
335
|
for (const full of bodies) {
|
|
336
336
|
try {
|
|
337
337
|
yield await ModelCrudUtil.load(cls, full);
|
|
338
|
-
} catch (
|
|
339
|
-
if (!(
|
|
340
|
-
throw
|
|
338
|
+
} catch (error) {
|
|
339
|
+
if (!(error instanceof NotFoundError)) {
|
|
340
|
+
throw error;
|
|
341
341
|
}
|
|
342
342
|
}
|
|
343
343
|
}
|