@travetto/cache 4.0.7 → 4.1.0
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 -5
- package/support/test/service.ts +46 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/cache",
|
|
3
|
-
"version": "4.0
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"description": "Caching functionality with decorators for declarative use.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -25,12 +25,12 @@
|
|
|
25
25
|
"directory": "module/cache"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@travetto/di": "^4.0
|
|
29
|
-
"@travetto/model": "^4.0
|
|
28
|
+
"@travetto/di": "^4.1.0",
|
|
29
|
+
"@travetto/model": "^4.1.0"
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
|
-
"@travetto/test": "^4.0
|
|
33
|
-
"@travetto/transformer": "^4.0
|
|
32
|
+
"@travetto/test": "^4.1.0",
|
|
33
|
+
"@travetto/transformer": "^4.1.0"
|
|
34
34
|
},
|
|
35
35
|
"peerDependenciesMeta": {
|
|
36
36
|
"@travetto/transformer": {
|
package/src/service.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { ExpiresAt, Model, ModelExpirySupport, NotFoundError } from '@travetto/model';
|
|
1
|
+
import { ExpiresAt, Index, Model, ModelExpirySupport, NotFoundError } from '@travetto/model';
|
|
2
2
|
import { Text } from '@travetto/schema';
|
|
3
3
|
import { Inject, Injectable } from '@travetto/di';
|
|
4
|
-
import { Env } from '@travetto/base';
|
|
5
|
-
import { isStorageSupported } from '@travetto/model/src/internal/service/common';
|
|
4
|
+
import { AppError, Env } from '@travetto/base';
|
|
5
|
+
import { isIndexedSupported, isStorageSupported } from '@travetto/model/src/internal/service/common';
|
|
6
6
|
|
|
7
7
|
import { CacheError } from './error';
|
|
8
8
|
import { CacheUtil } from './util';
|
|
@@ -12,11 +12,17 @@ export const CacheModelⲐ = Symbol.for('@travetto/cache:model');
|
|
|
12
12
|
|
|
13
13
|
const INFINITE_MAX_AGE = '5000-01-01';
|
|
14
14
|
|
|
15
|
+
@Index({
|
|
16
|
+
name: 'keySpace',
|
|
17
|
+
type: 'unsorted',
|
|
18
|
+
fields: [{ keySpace: 1 }]
|
|
19
|
+
})
|
|
15
20
|
@Model({ autoCreate: false })
|
|
16
21
|
export class CacheRecord {
|
|
17
22
|
id: string;
|
|
18
23
|
@Text()
|
|
19
24
|
entry: string;
|
|
25
|
+
keySpace: string;
|
|
20
26
|
@ExpiresAt()
|
|
21
27
|
expiresAt: Date;
|
|
22
28
|
issuedAt: Date;
|
|
@@ -77,13 +83,14 @@ export class CacheService {
|
|
|
77
83
|
* @param maxAge Max age in ms
|
|
78
84
|
* @returns
|
|
79
85
|
*/
|
|
80
|
-
async set(id: string, entry: unknown, maxAge?: number): Promise<unknown> {
|
|
86
|
+
async set(id: string, keySpace: string, entry: unknown, maxAge?: number): Promise<unknown> {
|
|
81
87
|
const entryText = CacheUtil.toSafeJSON(entry);
|
|
82
88
|
|
|
83
89
|
const store = await this.#modelService.upsert(CacheRecord,
|
|
84
90
|
CacheRecord.from({
|
|
85
91
|
id,
|
|
86
92
|
entry: entryText!,
|
|
93
|
+
keySpace,
|
|
87
94
|
expiresAt: new Date(maxAge ? maxAge + Date.now() : INFINITE_MAX_AGE),
|
|
88
95
|
issuedAt: new Date()
|
|
89
96
|
}),
|
|
@@ -100,6 +107,22 @@ export class CacheService {
|
|
|
100
107
|
await this.#modelService.delete(CacheRecord, id);
|
|
101
108
|
}
|
|
102
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Remove all entries by key space
|
|
112
|
+
* @param id
|
|
113
|
+
*/
|
|
114
|
+
async deleteAll(keySpace: string): Promise<void> {
|
|
115
|
+
if (isIndexedSupported(this.#modelService)) {
|
|
116
|
+
const removes: Promise<void>[] = [];
|
|
117
|
+
for await (const item of this.#modelService.listByIndex(CacheRecord, 'keySpace', { keySpace })) {
|
|
118
|
+
removes.push(this.#modelService.delete(CacheRecord, item.id));
|
|
119
|
+
}
|
|
120
|
+
await Promise.all(removes);
|
|
121
|
+
} else {
|
|
122
|
+
throw new AppError('Unable to delete all on an un-indexed database', 'general');
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
103
126
|
/**
|
|
104
127
|
* Purge the cache store of all data, if supported
|
|
105
128
|
*/
|
|
@@ -146,7 +169,7 @@ export class CacheService {
|
|
|
146
169
|
|
|
147
170
|
if (res === undefined) {
|
|
148
171
|
const data = await fn.apply(target, params);
|
|
149
|
-
res = await this.set(id, data, config.maxAge);
|
|
172
|
+
res = await this.set(id, config.keySpace!, data, config.maxAge);
|
|
150
173
|
}
|
|
151
174
|
|
|
152
175
|
if (config.reinstate) { // Reinstate result value if needed
|
package/support/test/service.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { ModelExpirySupport } from '@travetto/model';
|
|
|
6
6
|
import { Inject, Injectable } from '@travetto/di';
|
|
7
7
|
import { InjectableSuite } from '@travetto/di/support/test/suite';
|
|
8
8
|
import { ModelSuite } from '@travetto/model/support/test/suite';
|
|
9
|
+
import { isIndexedSupported } from '@travetto/model/src/internal/service/common';
|
|
9
10
|
import { Class } from '@travetto/base';
|
|
10
11
|
import { Schema } from '@travetto/schema';
|
|
11
12
|
|
|
@@ -72,6 +73,12 @@ class SampleService {
|
|
|
72
73
|
await timers.setTimeout(100);
|
|
73
74
|
return true;
|
|
74
75
|
}
|
|
76
|
+
|
|
77
|
+
async deleteAllUsers() {
|
|
78
|
+
this.source.deleteAll('user.id');
|
|
79
|
+
await timers.setTimeout(100);
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
75
82
|
}
|
|
76
83
|
|
|
77
84
|
@Suite()
|
|
@@ -209,4 +216,43 @@ export abstract class CacheServiceSuite {
|
|
|
209
216
|
|
|
210
217
|
await assert.doesNotReject(() => service.deleteUser('200'));
|
|
211
218
|
}
|
|
219
|
+
|
|
220
|
+
@Test()
|
|
221
|
+
async allEviction() {
|
|
222
|
+
if (!isIndexedSupported(this.serviceClass.prototype)) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const service = await this.testService;
|
|
227
|
+
|
|
228
|
+
// Prime cache
|
|
229
|
+
for (let i = 0; i < 10; i++) {
|
|
230
|
+
const start = Date.now();
|
|
231
|
+
await service.getUser(`${i}`);
|
|
232
|
+
assert((Date.now() - start) >= 100);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Read cache
|
|
236
|
+
for (let i = 0; i < 10; i++) {
|
|
237
|
+
const start = Date.now();
|
|
238
|
+
await service.getUser(`${i}`);
|
|
239
|
+
assert((Date.now() - start) <= (this.baseLatency + 100));
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
await service.deleteAllUsers();
|
|
243
|
+
|
|
244
|
+
// Prime cache
|
|
245
|
+
for (let i = 0; i < 10; i++) {
|
|
246
|
+
const start = Date.now();
|
|
247
|
+
await service.getUser(`${i}`);
|
|
248
|
+
assert((Date.now() - start) >= 100);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Read cache
|
|
252
|
+
for (let i = 0; i < 10; i++) {
|
|
253
|
+
const start = Date.now();
|
|
254
|
+
await service.getUser(`${i}`);
|
|
255
|
+
assert((Date.now() - start) <= (this.baseLatency + 100));
|
|
256
|
+
}
|
|
257
|
+
}
|
|
212
258
|
}
|