@expo/entity-cache-adapter-redis 0.41.0 → 0.42.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/build/GenericRedisCacher.d.ts +26 -4
- package/build/GenericRedisCacher.js +36 -5
- package/build/GenericRedisCacher.js.map +1 -1
- package/build/RedisCacheAdapterProvider.d.ts +1 -1
- package/build/RedisCacheAdapterProvider.js.map +1 -1
- package/build/index.d.ts +1 -0
- package/build/index.js +1 -0
- package/build/index.js.map +1 -1
- package/build/tsconfig.build.tsbuildinfo +1 -0
- package/build/utils/getSurroundingCacheKeyVersionsForInvalidation.d.ts +1 -0
- package/build/utils/getSurroundingCacheKeyVersionsForInvalidation.js +11 -0
- package/build/utils/getSurroundingCacheKeyVersionsForInvalidation.js.map +1 -0
- package/package.json +9 -7
- package/src/GenericRedisCacher.ts +72 -13
- package/src/RedisCacheAdapterProvider.ts +3 -3
- package/src/__integration-tests__/BatchedRedisCacheAdapter-integration-test.ts +29 -11
- package/src/__integration-tests__/GenericRedisCacher-full-integration-test.ts +83 -18
- package/src/__integration-tests__/GenericRedisCacher-integration-test.ts +7 -3
- package/src/__integration-tests__/errors-test.ts +7 -3
- package/src/{testfixtures → __testfixtures__}/RedisTestEntity.ts +13 -29
- package/src/{testfixtures → __testfixtures__}/createRedisIntegrationTestEntityCompanionProvider.ts +1 -2
- package/src/__tests__/GenericRedisCacher-test.ts +68 -12
- package/src/index.ts +1 -0
- package/src/utils/__tests__/getSurroundingCacheKeyVersionsForInvalidation-test.ts +9 -0
- package/src/utils/getSurroundingCacheKeyVersionsForInvalidation.ts +9 -0
- package/build/__integration-tests__/BatchedRedisCacheAdapter-integration-test.d.ts +0 -1
- package/build/__integration-tests__/BatchedRedisCacheAdapter-integration-test.js +0 -122
- package/build/__integration-tests__/BatchedRedisCacheAdapter-integration-test.js.map +0 -1
- package/build/__integration-tests__/GenericRedisCacher-full-integration-test.d.ts +0 -1
- package/build/__integration-tests__/GenericRedisCacher-full-integration-test.js +0 -93
- package/build/__integration-tests__/GenericRedisCacher-full-integration-test.js.map +0 -1
- package/build/__integration-tests__/GenericRedisCacher-integration-test.d.ts +0 -1
- package/build/__integration-tests__/GenericRedisCacher-integration-test.js +0 -122
- package/build/__integration-tests__/GenericRedisCacher-integration-test.js.map +0 -1
- package/build/__integration-tests__/errors-test.d.ts +0 -1
- package/build/__integration-tests__/errors-test.js +0 -39
- package/build/__integration-tests__/errors-test.js.map +0 -1
- package/build/__tests__/GenericRedisCacher-test.d.ts +0 -1
- package/build/__tests__/GenericRedisCacher-test.js +0 -141
- package/build/__tests__/GenericRedisCacher-test.js.map +0 -1
- package/build/errors/__tests__/wrapNativeRedisCallAsync-test.d.ts +0 -1
- package/build/errors/__tests__/wrapNativeRedisCallAsync-test.js +0 -42
- package/build/errors/__tests__/wrapNativeRedisCallAsync-test.js.map +0 -1
- package/build/testfixtures/RedisTestEntity.d.ts +0 -16
- package/build/testfixtures/RedisTestEntity.js +0 -49
- package/build/testfixtures/RedisTestEntity.js.map +0 -1
- package/build/testfixtures/createRedisIntegrationTestEntityCompanionProvider.d.ts +0 -3
- package/build/testfixtures/createRedisIntegrationTestEntityCompanionProvider.js +0 -31
- package/build/testfixtures/createRedisIntegrationTestEntityCompanionProvider.js.map +0 -1
|
@@ -2,12 +2,15 @@ import { CacheStatus, ViewerContext } from '@expo/entity';
|
|
|
2
2
|
import Redis from 'ioredis';
|
|
3
3
|
import { URL } from 'url';
|
|
4
4
|
|
|
5
|
-
import GenericRedisCacher, {
|
|
5
|
+
import GenericRedisCacher, {
|
|
6
|
+
GenericRedisCacheContext,
|
|
7
|
+
RedisCacheInvalidationStrategy,
|
|
8
|
+
} from '../GenericRedisCacher';
|
|
6
9
|
import RedisTestEntity, {
|
|
7
10
|
redisTestEntityConfiguration,
|
|
8
11
|
RedisTestEntityFields,
|
|
9
|
-
} from '../
|
|
10
|
-
import { createRedisIntegrationTestEntityCompanionProvider } from '../
|
|
12
|
+
} from '../__testfixtures__/RedisTestEntity';
|
|
13
|
+
import { createRedisIntegrationTestEntityCompanionProvider } from '../__testfixtures__/createRedisIntegrationTestEntityCompanionProvider';
|
|
11
14
|
|
|
12
15
|
class TestViewerContext extends ViewerContext {}
|
|
13
16
|
|
|
@@ -27,6 +30,7 @@ describe(GenericRedisCacher, () => {
|
|
|
27
30
|
cacheKeyPrefix: 'test-',
|
|
28
31
|
ttlSecondsPositive: 86400, // 1 day
|
|
29
32
|
ttlSecondsNegative: 600, // 10 minutes
|
|
33
|
+
invalidationStrategy: RedisCacheInvalidationStrategy.CURRENT_CACHE_KEY_VERSION,
|
|
30
34
|
};
|
|
31
35
|
});
|
|
32
36
|
|
|
@@ -2,9 +2,12 @@ import { EntityCacheAdapterTransientError, ViewerContext } from '@expo/entity';
|
|
|
2
2
|
import Redis from 'ioredis';
|
|
3
3
|
import { URL } from 'url';
|
|
4
4
|
|
|
5
|
-
import GenericRedisCacher, {
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
import GenericRedisCacher, {
|
|
6
|
+
GenericRedisCacheContext,
|
|
7
|
+
RedisCacheInvalidationStrategy,
|
|
8
|
+
} from '../GenericRedisCacher';
|
|
9
|
+
import RedisTestEntity from '../__testfixtures__/RedisTestEntity';
|
|
10
|
+
import { createRedisIntegrationTestEntityCompanionProvider } from '../__testfixtures__/createRedisIntegrationTestEntityCompanionProvider';
|
|
8
11
|
|
|
9
12
|
class TestViewerContext extends ViewerContext {}
|
|
10
13
|
|
|
@@ -25,6 +28,7 @@ describe(GenericRedisCacher, () => {
|
|
|
25
28
|
cacheKeyPrefix: 'test-',
|
|
26
29
|
ttlSecondsPositive: 86400, // 1 day
|
|
27
30
|
ttlSecondsNegative: 600, // 10 minutes
|
|
31
|
+
invalidationStrategy: RedisCacheInvalidationStrategy.CURRENT_CACHE_KEY_VERSION,
|
|
28
32
|
};
|
|
29
33
|
});
|
|
30
34
|
|
|
@@ -2,12 +2,12 @@ import {
|
|
|
2
2
|
AlwaysAllowPrivacyPolicyRule,
|
|
3
3
|
EntityPrivacyPolicy,
|
|
4
4
|
ViewerContext,
|
|
5
|
-
UUIDField,
|
|
6
5
|
DateField,
|
|
7
6
|
StringField,
|
|
8
7
|
EntityConfiguration,
|
|
9
8
|
EntityCompanionDefinition,
|
|
10
9
|
Entity,
|
|
10
|
+
UUIDField,
|
|
11
11
|
} from '@expo/entity';
|
|
12
12
|
|
|
13
13
|
export type RedisTestEntityFields = {
|
|
@@ -16,10 +16,10 @@ export type RedisTestEntityFields = {
|
|
|
16
16
|
dateField: Date | null;
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
export default class RedisTestEntity extends Entity<RedisTestEntityFields,
|
|
19
|
+
export default class RedisTestEntity extends Entity<RedisTestEntityFields, 'id', ViewerContext> {
|
|
20
20
|
static defineCompanionDefinition(): EntityCompanionDefinition<
|
|
21
21
|
RedisTestEntityFields,
|
|
22
|
-
|
|
22
|
+
'id',
|
|
23
23
|
ViewerContext,
|
|
24
24
|
RedisTestEntity,
|
|
25
25
|
RedisTestEntityPrivacyPolicy
|
|
@@ -34,45 +34,25 @@ export default class RedisTestEntity extends Entity<RedisTestEntityFields, strin
|
|
|
34
34
|
|
|
35
35
|
export class RedisTestEntityPrivacyPolicy extends EntityPrivacyPolicy<
|
|
36
36
|
RedisTestEntityFields,
|
|
37
|
-
|
|
37
|
+
'id',
|
|
38
38
|
ViewerContext,
|
|
39
39
|
RedisTestEntity
|
|
40
40
|
> {
|
|
41
41
|
protected override readonly createRules = [
|
|
42
|
-
new AlwaysAllowPrivacyPolicyRule<
|
|
43
|
-
RedisTestEntityFields,
|
|
44
|
-
string,
|
|
45
|
-
ViewerContext,
|
|
46
|
-
RedisTestEntity
|
|
47
|
-
>(),
|
|
42
|
+
new AlwaysAllowPrivacyPolicyRule<RedisTestEntityFields, 'id', ViewerContext, RedisTestEntity>(),
|
|
48
43
|
];
|
|
49
44
|
protected override readonly readRules = [
|
|
50
|
-
new AlwaysAllowPrivacyPolicyRule<
|
|
51
|
-
RedisTestEntityFields,
|
|
52
|
-
string,
|
|
53
|
-
ViewerContext,
|
|
54
|
-
RedisTestEntity
|
|
55
|
-
>(),
|
|
45
|
+
new AlwaysAllowPrivacyPolicyRule<RedisTestEntityFields, 'id', ViewerContext, RedisTestEntity>(),
|
|
56
46
|
];
|
|
57
47
|
protected override readonly updateRules = [
|
|
58
|
-
new AlwaysAllowPrivacyPolicyRule<
|
|
59
|
-
RedisTestEntityFields,
|
|
60
|
-
string,
|
|
61
|
-
ViewerContext,
|
|
62
|
-
RedisTestEntity
|
|
63
|
-
>(),
|
|
48
|
+
new AlwaysAllowPrivacyPolicyRule<RedisTestEntityFields, 'id', ViewerContext, RedisTestEntity>(),
|
|
64
49
|
];
|
|
65
50
|
protected override readonly deleteRules = [
|
|
66
|
-
new AlwaysAllowPrivacyPolicyRule<
|
|
67
|
-
RedisTestEntityFields,
|
|
68
|
-
string,
|
|
69
|
-
ViewerContext,
|
|
70
|
-
RedisTestEntity
|
|
71
|
-
>(),
|
|
51
|
+
new AlwaysAllowPrivacyPolicyRule<RedisTestEntityFields, 'id', ViewerContext, RedisTestEntity>(),
|
|
72
52
|
];
|
|
73
53
|
}
|
|
74
54
|
|
|
75
|
-
export const redisTestEntityConfiguration = new EntityConfiguration<RedisTestEntityFields>({
|
|
55
|
+
export const redisTestEntityConfiguration = new EntityConfiguration<RedisTestEntityFields, 'id'>({
|
|
76
56
|
idField: 'id',
|
|
77
57
|
tableName: 'redis_test_entities',
|
|
78
58
|
schema: {
|
|
@@ -90,4 +70,8 @@ export const redisTestEntityConfiguration = new EntityConfiguration<RedisTestEnt
|
|
|
90
70
|
},
|
|
91
71
|
databaseAdapterFlavor: 'postgres',
|
|
92
72
|
cacheAdapterFlavor: 'redis',
|
|
73
|
+
compositeFieldDefinitions: [
|
|
74
|
+
{ compositeField: ['id', 'name'], cache: true },
|
|
75
|
+
{ compositeField: ['id', 'dateField'], cache: true },
|
|
76
|
+
],
|
|
93
77
|
});
|
package/src/{testfixtures → __testfixtures__}/createRedisIntegrationTestEntityCompanionProvider.ts
RENAMED
|
@@ -2,9 +2,8 @@ import {
|
|
|
2
2
|
NoOpEntityMetricsAdapter,
|
|
3
3
|
IEntityMetricsAdapter,
|
|
4
4
|
EntityCompanionProvider,
|
|
5
|
-
StubQueryContextProvider,
|
|
6
|
-
StubDatabaseAdapterProvider,
|
|
7
5
|
} from '@expo/entity';
|
|
6
|
+
import { StubDatabaseAdapterProvider, StubQueryContextProvider } from '@expo/entity-testing-utils';
|
|
8
7
|
|
|
9
8
|
import { GenericRedisCacheContext } from '../GenericRedisCacher';
|
|
10
9
|
import RedisCacheAdapterProvider from '../RedisCacheAdapterProvider';
|
|
@@ -1,16 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
CacheStatus,
|
|
3
|
+
EntityConfiguration,
|
|
4
|
+
SingleFieldHolder,
|
|
5
|
+
SingleFieldValueHolder,
|
|
6
|
+
UUIDField,
|
|
7
|
+
} from '@expo/entity';
|
|
2
8
|
import { Redis, Pipeline } from 'ioredis';
|
|
3
9
|
import { mock, when, instance, anything, verify } from 'ts-mockito';
|
|
4
10
|
|
|
5
|
-
import GenericRedisCacher from '../GenericRedisCacher';
|
|
11
|
+
import GenericRedisCacher, { RedisCacheInvalidationStrategy } from '../GenericRedisCacher';
|
|
6
12
|
|
|
7
13
|
type BlahFields = {
|
|
8
14
|
id: string;
|
|
9
15
|
};
|
|
10
16
|
|
|
11
|
-
const entityConfiguration = new EntityConfiguration<BlahFields>({
|
|
17
|
+
const entityConfiguration = new EntityConfiguration<BlahFields, 'id'>({
|
|
12
18
|
idField: 'id',
|
|
13
19
|
tableName: 'blah',
|
|
20
|
+
cacheKeyVersion: 2,
|
|
14
21
|
schema: {
|
|
15
22
|
id: new UUIDField({ columnName: 'id', cache: true }),
|
|
16
23
|
},
|
|
@@ -37,13 +44,23 @@ describe(GenericRedisCacher, () => {
|
|
|
37
44
|
cacheKeyPrefix: 'hello-',
|
|
38
45
|
ttlSecondsPositive: 1,
|
|
39
46
|
ttlSecondsNegative: 2,
|
|
47
|
+
invalidationStrategy: RedisCacheInvalidationStrategy.CURRENT_CACHE_KEY_VERSION,
|
|
40
48
|
},
|
|
41
49
|
entityConfiguration,
|
|
42
50
|
);
|
|
43
51
|
|
|
44
|
-
const cacheKeyWat = genericCacher['
|
|
45
|
-
|
|
46
|
-
|
|
52
|
+
const cacheKeyWat = genericCacher['makeCacheKeyForStorage'](
|
|
53
|
+
new SingleFieldHolder('id'),
|
|
54
|
+
new SingleFieldValueHolder('wat'),
|
|
55
|
+
);
|
|
56
|
+
const cacheKeyWho = genericCacher['makeCacheKeyForStorage'](
|
|
57
|
+
new SingleFieldHolder('id'),
|
|
58
|
+
new SingleFieldValueHolder('who'),
|
|
59
|
+
);
|
|
60
|
+
const cacheKeyWhy = genericCacher['makeCacheKeyForStorage'](
|
|
61
|
+
new SingleFieldHolder('id'),
|
|
62
|
+
new SingleFieldValueHolder('why'),
|
|
63
|
+
);
|
|
47
64
|
|
|
48
65
|
redisResults.set(cacheKeyWat, JSON.stringify({ id: 'wat' }));
|
|
49
66
|
redisResults.set(cacheKeyWho, '');
|
|
@@ -67,6 +84,7 @@ describe(GenericRedisCacher, () => {
|
|
|
67
84
|
cacheKeyPrefix: 'hello-',
|
|
68
85
|
ttlSecondsPositive: 1,
|
|
69
86
|
ttlSecondsNegative: 2,
|
|
87
|
+
invalidationStrategy: RedisCacheInvalidationStrategy.CURRENT_CACHE_KEY_VERSION,
|
|
70
88
|
},
|
|
71
89
|
entityConfiguration,
|
|
72
90
|
);
|
|
@@ -99,11 +117,15 @@ describe(GenericRedisCacher, () => {
|
|
|
99
117
|
cacheKeyPrefix: 'hello-',
|
|
100
118
|
ttlSecondsPositive: 1,
|
|
101
119
|
ttlSecondsNegative: 2,
|
|
120
|
+
invalidationStrategy: RedisCacheInvalidationStrategy.CURRENT_CACHE_KEY_VERSION,
|
|
102
121
|
},
|
|
103
122
|
entityConfiguration,
|
|
104
123
|
);
|
|
105
124
|
|
|
106
|
-
const cacheKey = genericCacher['
|
|
125
|
+
const cacheKey = genericCacher['makeCacheKeyForStorage'](
|
|
126
|
+
new SingleFieldHolder('id'),
|
|
127
|
+
new SingleFieldValueHolder('wat'),
|
|
128
|
+
);
|
|
107
129
|
|
|
108
130
|
await genericCacher.cacheManyAsync(new Map([[cacheKey, { id: 'wat' }]]));
|
|
109
131
|
|
|
@@ -138,11 +160,15 @@ describe(GenericRedisCacher, () => {
|
|
|
138
160
|
cacheKeyPrefix: 'hello-',
|
|
139
161
|
ttlSecondsPositive: 1,
|
|
140
162
|
ttlSecondsNegative: 2,
|
|
163
|
+
invalidationStrategy: RedisCacheInvalidationStrategy.CURRENT_CACHE_KEY_VERSION,
|
|
141
164
|
},
|
|
142
165
|
entityConfiguration,
|
|
143
166
|
);
|
|
144
167
|
|
|
145
|
-
const cacheKey = genericCacher['
|
|
168
|
+
const cacheKey = genericCacher['makeCacheKeyForStorage'](
|
|
169
|
+
new SingleFieldHolder('id'),
|
|
170
|
+
new SingleFieldValueHolder('wat'),
|
|
171
|
+
);
|
|
146
172
|
|
|
147
173
|
await genericCacher.cacheDBMissesAsync([cacheKey]);
|
|
148
174
|
|
|
@@ -155,7 +181,7 @@ describe(GenericRedisCacher, () => {
|
|
|
155
181
|
});
|
|
156
182
|
|
|
157
183
|
describe('invalidateManyAsync', () => {
|
|
158
|
-
it('invalidates correctly', async () => {
|
|
184
|
+
it('invalidates correctly with RedisCacheInvalidationStrategy.CURRENT_CACHE_KEY_VERSION', async () => {
|
|
159
185
|
const mockRedisClient = mock<Redis>();
|
|
160
186
|
when(mockRedisClient.del()).thenResolve(1);
|
|
161
187
|
|
|
@@ -166,14 +192,43 @@ describe(GenericRedisCacher, () => {
|
|
|
166
192
|
cacheKeyPrefix: 'hello-',
|
|
167
193
|
ttlSecondsPositive: 1,
|
|
168
194
|
ttlSecondsNegative: 2,
|
|
195
|
+
invalidationStrategy: RedisCacheInvalidationStrategy.CURRENT_CACHE_KEY_VERSION,
|
|
169
196
|
},
|
|
170
197
|
entityConfiguration,
|
|
171
198
|
);
|
|
172
|
-
const
|
|
199
|
+
const cacheKeys = genericCacher['makeCacheKeysForInvalidation'](
|
|
200
|
+
new SingleFieldHolder('id'),
|
|
201
|
+
new SingleFieldValueHolder('wat'),
|
|
202
|
+
);
|
|
203
|
+
expect(cacheKeys).toHaveLength(1);
|
|
204
|
+
|
|
205
|
+
await genericCacher.invalidateManyAsync(cacheKeys);
|
|
206
|
+
verify(mockRedisClient.del(...cacheKeys)).once();
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it('invalidates correctly with RedisCacheInvalidationStrategy.SURROUNDING_CACHE_KEY_VERSIONS', async () => {
|
|
210
|
+
const mockRedisClient = mock<Redis>();
|
|
211
|
+
when(mockRedisClient.del()).thenResolve(1);
|
|
173
212
|
|
|
174
|
-
|
|
213
|
+
const genericCacher = new GenericRedisCacher(
|
|
214
|
+
{
|
|
215
|
+
redisClient: instance(mockRedisClient),
|
|
216
|
+
makeKeyFn: (...parts) => parts.join(':'),
|
|
217
|
+
cacheKeyPrefix: 'hello-',
|
|
218
|
+
ttlSecondsPositive: 1,
|
|
219
|
+
ttlSecondsNegative: 2,
|
|
220
|
+
invalidationStrategy: RedisCacheInvalidationStrategy.SURROUNDING_CACHE_KEY_VERSIONS,
|
|
221
|
+
},
|
|
222
|
+
entityConfiguration,
|
|
223
|
+
);
|
|
224
|
+
const cacheKeys = genericCacher['makeCacheKeysForInvalidation'](
|
|
225
|
+
new SingleFieldHolder('id'),
|
|
226
|
+
new SingleFieldValueHolder('wat'),
|
|
227
|
+
);
|
|
228
|
+
expect(cacheKeys).toHaveLength(3);
|
|
175
229
|
|
|
176
|
-
|
|
230
|
+
await genericCacher.invalidateManyAsync(cacheKeys);
|
|
231
|
+
verify(mockRedisClient.del(...cacheKeys)).once();
|
|
177
232
|
});
|
|
178
233
|
|
|
179
234
|
it('returns when passed empty array of fieldValues', async () => {
|
|
@@ -184,6 +239,7 @@ describe(GenericRedisCacher, () => {
|
|
|
184
239
|
cacheKeyPrefix: 'hello-',
|
|
185
240
|
ttlSecondsPositive: 1,
|
|
186
241
|
ttlSecondsNegative: 2,
|
|
242
|
+
invalidationStrategy: RedisCacheInvalidationStrategy.CURRENT_CACHE_KEY_VERSION,
|
|
187
243
|
},
|
|
188
244
|
entityConfiguration,
|
|
189
245
|
);
|
package/src/index.ts
CHANGED
|
@@ -9,3 +9,4 @@ export * from './GenericRedisCacher';
|
|
|
9
9
|
export { default as RedisCacheAdapterProvider } from './RedisCacheAdapterProvider';
|
|
10
10
|
export * from './RedisCommon';
|
|
11
11
|
export { default as wrapNativeRedisCallAsync } from './errors/wrapNativeRedisCallAsync';
|
|
12
|
+
export * from './utils/getSurroundingCacheKeyVersionsForInvalidation';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { getSurroundingCacheKeyVersionsForInvalidation } from '../getSurroundingCacheKeyVersionsForInvalidation';
|
|
2
|
+
|
|
3
|
+
describe(getSurroundingCacheKeyVersionsForInvalidation, () => {
|
|
4
|
+
it('returns the correct cache key versions to invalidate', () => {
|
|
5
|
+
expect(getSurroundingCacheKeyVersionsForInvalidation(0)).toEqual([0, 1]);
|
|
6
|
+
expect(getSurroundingCacheKeyVersionsForInvalidation(1)).toEqual([0, 1, 2]);
|
|
7
|
+
expect(getSurroundingCacheKeyVersionsForInvalidation(2)).toEqual([1, 2, 3]);
|
|
8
|
+
});
|
|
9
|
+
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const batcher_1 = require("@expo/batcher");
|
|
7
|
-
const entity_1 = require("@expo/entity");
|
|
8
|
-
const invariant_1 = __importDefault(require("invariant"));
|
|
9
|
-
const ioredis_1 = __importDefault(require("ioredis"));
|
|
10
|
-
const nullthrows_1 = __importDefault(require("nullthrows"));
|
|
11
|
-
const url_1 = require("url");
|
|
12
|
-
const uuid_1 = require("uuid");
|
|
13
|
-
const GenericRedisCacher_1 = __importDefault(require("../GenericRedisCacher"));
|
|
14
|
-
const RedisTestEntity_1 = __importDefault(require("../testfixtures/RedisTestEntity"));
|
|
15
|
-
const createRedisIntegrationTestEntityCompanionProvider_1 = require("../testfixtures/createRedisIntegrationTestEntityCompanionProvider");
|
|
16
|
-
class BatchedRedis {
|
|
17
|
-
redis;
|
|
18
|
-
mgetBatcher = new batcher_1.Batcher(this.batchMgetAsync.bind(this), {
|
|
19
|
-
maxBatchInterval: 0,
|
|
20
|
-
});
|
|
21
|
-
constructor(redis) {
|
|
22
|
-
this.redis = redis;
|
|
23
|
-
}
|
|
24
|
-
async batchMgetAsync(keySets) {
|
|
25
|
-
// ordered distinct keys to fetch
|
|
26
|
-
const allKeysToFetch = [...new Set(keySets.flat())];
|
|
27
|
-
// fetch the distinct keys
|
|
28
|
-
const allResults = await this.redis.mget(...allKeysToFetch);
|
|
29
|
-
// put them into a map for fast lookup
|
|
30
|
-
const keysToResults = (0, entity_1.zipToMap)(allKeysToFetch, allResults);
|
|
31
|
-
// re-associate them with original key sets
|
|
32
|
-
return keySets.map((keySet) => keySet.map((key) => {
|
|
33
|
-
const result = keysToResults.get(key);
|
|
34
|
-
(0, invariant_1.default)(result !== undefined, 'result should not be undefined');
|
|
35
|
-
return result;
|
|
36
|
-
}));
|
|
37
|
-
}
|
|
38
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
39
|
-
async mget(...args) {
|
|
40
|
-
return await this.mgetBatcher.batchAsync(args);
|
|
41
|
-
}
|
|
42
|
-
multi() {
|
|
43
|
-
return this.redis.multi();
|
|
44
|
-
}
|
|
45
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
46
|
-
async del(...args) {
|
|
47
|
-
await this.redis.del(...args);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
describe(GenericRedisCacher_1.default, () => {
|
|
51
|
-
const redis = new ioredis_1.default(new url_1.URL(process.env['REDIS_URL']).toString());
|
|
52
|
-
const redisClient = new BatchedRedis(redis);
|
|
53
|
-
let genericRedisCacheContext;
|
|
54
|
-
beforeAll(() => {
|
|
55
|
-
genericRedisCacheContext = {
|
|
56
|
-
redisClient,
|
|
57
|
-
makeKeyFn(...parts) {
|
|
58
|
-
const delimiter = ':';
|
|
59
|
-
const escapedParts = parts.map((part) => part.replace('\\', '\\\\').replace(delimiter, `\\${delimiter}`));
|
|
60
|
-
return escapedParts.join(delimiter);
|
|
61
|
-
},
|
|
62
|
-
cacheKeyPrefix: 'test-',
|
|
63
|
-
ttlSecondsPositive: 86400, // 1 day
|
|
64
|
-
ttlSecondsNegative: 600, // 10 minutes
|
|
65
|
-
};
|
|
66
|
-
});
|
|
67
|
-
beforeEach(async () => {
|
|
68
|
-
await redis.flushdb();
|
|
69
|
-
});
|
|
70
|
-
afterAll(async () => {
|
|
71
|
-
redis.disconnect();
|
|
72
|
-
});
|
|
73
|
-
it('has correct caching behavior', async () => {
|
|
74
|
-
// simulate two requests
|
|
75
|
-
const viewerContext = new entity_1.ViewerContext((0, createRedisIntegrationTestEntityCompanionProvider_1.createRedisIntegrationTestEntityCompanionProvider)(genericRedisCacheContext));
|
|
76
|
-
const mgetSpy = jest.spyOn(redis, 'mget');
|
|
77
|
-
const genericCacher = viewerContext.entityCompanionProvider.getCompanionForEntity(RedisTestEntity_1.default)['tableDataCoordinator']['cacheAdapter']['genericCacher'];
|
|
78
|
-
const cacheKeyMaker = genericCacher['makeCacheKey'].bind(genericCacher);
|
|
79
|
-
const entity1Created = await RedisTestEntity_1.default.creator(viewerContext)
|
|
80
|
-
.setField('name', 'blah')
|
|
81
|
-
.createAsync();
|
|
82
|
-
// loading an entity should put it in cache. load by multiple requests and multiple fields in same tick to ensure batch works
|
|
83
|
-
mgetSpy.mockClear();
|
|
84
|
-
const viewerContext1 = new entity_1.ViewerContext((0, createRedisIntegrationTestEntityCompanionProvider_1.createRedisIntegrationTestEntityCompanionProvider)(genericRedisCacheContext));
|
|
85
|
-
const viewerContext2 = new entity_1.ViewerContext((0, createRedisIntegrationTestEntityCompanionProvider_1.createRedisIntegrationTestEntityCompanionProvider)(genericRedisCacheContext));
|
|
86
|
-
const viewerContext3 = new entity_1.ViewerContext((0, createRedisIntegrationTestEntityCompanionProvider_1.createRedisIntegrationTestEntityCompanionProvider)(genericRedisCacheContext));
|
|
87
|
-
const [entity1, entity2, entity3] = await Promise.all([
|
|
88
|
-
RedisTestEntity_1.default.loader(viewerContext1).loadByIDAsync(entity1Created.getID()),
|
|
89
|
-
RedisTestEntity_1.default.loader(viewerContext2).loadByIDAsync(entity1Created.getID()),
|
|
90
|
-
RedisTestEntity_1.default.loader(viewerContext3).loadByFieldEqualingAsync('name', entity1Created.getField('name')),
|
|
91
|
-
]);
|
|
92
|
-
expect(mgetSpy).toHaveBeenCalledTimes(1);
|
|
93
|
-
expect(mgetSpy.mock.calls[0]).toHaveLength(2); // should dedupe the first two loads
|
|
94
|
-
expect(entity1.getID()).toEqual(entity2.getID());
|
|
95
|
-
expect(entity2.getID()).toEqual((0, nullthrows_1.default)(entity3).getID());
|
|
96
|
-
const cacheKeyEntity1 = cacheKeyMaker('id', entity1Created.getID());
|
|
97
|
-
const cachedJSON = await redis.get(cacheKeyEntity1);
|
|
98
|
-
const cachedValue = JSON.parse(cachedJSON);
|
|
99
|
-
expect(cachedValue).toMatchObject({
|
|
100
|
-
id: entity1.getID(),
|
|
101
|
-
name: 'blah',
|
|
102
|
-
});
|
|
103
|
-
const cacheKeyEntity1NameField = cacheKeyMaker('name', entity1Created.getField('name'));
|
|
104
|
-
await RedisTestEntity_1.default.loader(viewerContext).loadByFieldEqualingAsync('name', entity1Created.getField('name'));
|
|
105
|
-
await expect(redis.get(cacheKeyEntity1NameField)).resolves.toEqual(cachedJSON);
|
|
106
|
-
// simulate non existent db fetch, should write negative result ('') to cache
|
|
107
|
-
const nonExistentId = (0, uuid_1.v4)();
|
|
108
|
-
const entityNonExistentResult = await RedisTestEntity_1.default.loaderWithAuthorizationResults(viewerContext).loadByIDAsync(nonExistentId);
|
|
109
|
-
expect(entityNonExistentResult.ok).toBe(false);
|
|
110
|
-
const cacheKeyNonExistent = cacheKeyMaker('id', nonExistentId);
|
|
111
|
-
const nonExistentCachedValue = await redis.get(cacheKeyNonExistent);
|
|
112
|
-
expect(nonExistentCachedValue).toEqual('');
|
|
113
|
-
// load again through entities framework to ensure it reads negative result
|
|
114
|
-
const entityNonExistentResult2 = await RedisTestEntity_1.default.loaderWithAuthorizationResults(viewerContext).loadByIDAsync(nonExistentId);
|
|
115
|
-
expect(entityNonExistentResult2.ok).toBe(false);
|
|
116
|
-
// invalidate from cache to ensure it invalidates correctly in both caches
|
|
117
|
-
await RedisTestEntity_1.default.loaderUtils(viewerContext).invalidateFieldsAsync(entity1.getAllFields());
|
|
118
|
-
await expect(redis.get(cacheKeyEntity1)).resolves.toBeNull();
|
|
119
|
-
await expect(redis.get(cacheKeyEntity1NameField)).resolves.toBeNull();
|
|
120
|
-
});
|
|
121
|
-
});
|
|
122
|
-
//# sourceMappingURL=BatchedRedisCacheAdapter-integration-test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"BatchedRedisCacheAdapter-integration-test.js","sourceRoot":"","sources":["../../src/__integration-tests__/BatchedRedisCacheAdapter-integration-test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const entity_1 = require("@expo/entity");
|
|
7
|
-
const results_1 = require("@expo/results");
|
|
8
|
-
const ioredis_1 = __importDefault(require("ioredis"));
|
|
9
|
-
const url_1 = require("url");
|
|
10
|
-
const uuid_1 = require("uuid");
|
|
11
|
-
const GenericRedisCacher_1 = __importDefault(require("../GenericRedisCacher"));
|
|
12
|
-
const RedisTestEntity_1 = __importDefault(require("../testfixtures/RedisTestEntity"));
|
|
13
|
-
const createRedisIntegrationTestEntityCompanionProvider_1 = require("../testfixtures/createRedisIntegrationTestEntityCompanionProvider");
|
|
14
|
-
class TestViewerContext extends entity_1.ViewerContext {
|
|
15
|
-
}
|
|
16
|
-
describe(GenericRedisCacher_1.default, () => {
|
|
17
|
-
let genericRedisCacheContext;
|
|
18
|
-
beforeAll(() => {
|
|
19
|
-
genericRedisCacheContext = {
|
|
20
|
-
redisClient: new ioredis_1.default(new url_1.URL(process.env['REDIS_URL']).toString()),
|
|
21
|
-
makeKeyFn(...parts) {
|
|
22
|
-
const delimiter = ':';
|
|
23
|
-
const escapedParts = parts.map((part) => part.replace('\\', '\\\\').replace(delimiter, `\\${delimiter}`));
|
|
24
|
-
return escapedParts.join(delimiter);
|
|
25
|
-
},
|
|
26
|
-
cacheKeyPrefix: 'test-',
|
|
27
|
-
ttlSecondsPositive: 86400, // 1 day
|
|
28
|
-
ttlSecondsNegative: 600, // 10 minutes
|
|
29
|
-
};
|
|
30
|
-
});
|
|
31
|
-
beforeEach(async () => {
|
|
32
|
-
await genericRedisCacheContext.redisClient.flushdb();
|
|
33
|
-
});
|
|
34
|
-
afterAll(async () => {
|
|
35
|
-
genericRedisCacheContext.redisClient.disconnect();
|
|
36
|
-
});
|
|
37
|
-
it('has correct caching behavior', async () => {
|
|
38
|
-
const viewerContext = new TestViewerContext((0, createRedisIntegrationTestEntityCompanionProvider_1.createRedisIntegrationTestEntityCompanionProvider)(genericRedisCacheContext));
|
|
39
|
-
const genericCacher = viewerContext.entityCompanionProvider.getCompanionForEntity(RedisTestEntity_1.default)['tableDataCoordinator']['cacheAdapter']['genericCacher'];
|
|
40
|
-
const cacheKeyMaker = genericCacher['makeCacheKey'].bind(genericCacher);
|
|
41
|
-
const entity1Created = await RedisTestEntity_1.default.creator(viewerContext)
|
|
42
|
-
.setField('name', 'blah')
|
|
43
|
-
.createAsync();
|
|
44
|
-
// loading an entity should put it in cache
|
|
45
|
-
const entity1 = await RedisTestEntity_1.default.loader(viewerContext).loadByIDAsync(entity1Created.getID());
|
|
46
|
-
const cachedJSON = await genericRedisCacheContext.redisClient.get(cacheKeyMaker('id', entity1.getID()));
|
|
47
|
-
const cachedValue = JSON.parse(cachedJSON);
|
|
48
|
-
expect(cachedValue).toMatchObject({
|
|
49
|
-
id: entity1.getID(),
|
|
50
|
-
name: 'blah',
|
|
51
|
-
});
|
|
52
|
-
// simulate non existent db fetch, should write negative result ('') to cache
|
|
53
|
-
const nonExistentId = (0, uuid_1.v4)();
|
|
54
|
-
const entityNonExistentResult = await RedisTestEntity_1.default.loaderWithAuthorizationResults(viewerContext).loadByIDAsync(nonExistentId);
|
|
55
|
-
expect(entityNonExistentResult.ok).toBe(false);
|
|
56
|
-
const nonExistentCachedValue = await genericRedisCacheContext.redisClient.get(cacheKeyMaker('id', nonExistentId));
|
|
57
|
-
expect(nonExistentCachedValue).toEqual('');
|
|
58
|
-
// load again through entities framework to ensure it reads negative result
|
|
59
|
-
const entityNonExistentResult2 = await RedisTestEntity_1.default.loaderWithAuthorizationResults(viewerContext).loadByIDAsync(nonExistentId);
|
|
60
|
-
expect(entityNonExistentResult2.ok).toBe(false);
|
|
61
|
-
// invalidate from cache to ensure it invalidates correctly
|
|
62
|
-
await RedisTestEntity_1.default.loaderUtils(viewerContext).invalidateFieldsAsync(entity1.getAllFields());
|
|
63
|
-
const cachedValueNull = await genericRedisCacheContext.redisClient.get(cacheKeyMaker('id', entity1.getID()));
|
|
64
|
-
expect(cachedValueNull).toBe(null);
|
|
65
|
-
});
|
|
66
|
-
it('caches and restores date fields', async () => {
|
|
67
|
-
const viewerContext = new TestViewerContext((0, createRedisIntegrationTestEntityCompanionProvider_1.createRedisIntegrationTestEntityCompanionProvider)(genericRedisCacheContext));
|
|
68
|
-
const date = new Date();
|
|
69
|
-
const entity1 = await (0, results_1.enforceAsyncResult)(RedisTestEntity_1.default.creatorWithAuthorizationResults(viewerContext)
|
|
70
|
-
.setField('dateField', date)
|
|
71
|
-
.createAsync());
|
|
72
|
-
expect(entity1.getField('dateField')).toEqual(date);
|
|
73
|
-
const entity2 = await RedisTestEntity_1.default.loader(viewerContext).loadByIDAsync(entity1.getID());
|
|
74
|
-
expect(entity2.getField('dateField')).toEqual(date);
|
|
75
|
-
// simulate new request
|
|
76
|
-
const vc2 = new TestViewerContext((0, createRedisIntegrationTestEntityCompanionProvider_1.createRedisIntegrationTestEntityCompanionProvider)(genericRedisCacheContext));
|
|
77
|
-
const entity3 = await RedisTestEntity_1.default.loader(vc2).loadByIDAsync(entity1.getID());
|
|
78
|
-
expect(entity3.getField('dateField')).toEqual(date);
|
|
79
|
-
});
|
|
80
|
-
it('caches and restores empty string field keys', async () => {
|
|
81
|
-
const viewerContext = new TestViewerContext((0, createRedisIntegrationTestEntityCompanionProvider_1.createRedisIntegrationTestEntityCompanionProvider)(genericRedisCacheContext));
|
|
82
|
-
const entity1 = await (0, results_1.enforceAsyncResult)(RedisTestEntity_1.default.creatorWithAuthorizationResults(viewerContext)
|
|
83
|
-
.setField('name', '')
|
|
84
|
-
.createAsync());
|
|
85
|
-
const entity2 = await RedisTestEntity_1.default.loader(viewerContext).loadByFieldEqualingAsync('name', '');
|
|
86
|
-
expect(entity2?.getID()).toEqual(entity1.getID());
|
|
87
|
-
// simulate new request
|
|
88
|
-
const vc2 = new TestViewerContext((0, createRedisIntegrationTestEntityCompanionProvider_1.createRedisIntegrationTestEntityCompanionProvider)(genericRedisCacheContext));
|
|
89
|
-
const entity3 = await RedisTestEntity_1.default.loader(vc2).loadByFieldEqualingAsync('name', '');
|
|
90
|
-
expect(entity3?.getID()).toEqual(entity1.getID());
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
//# sourceMappingURL=GenericRedisCacher-full-integration-test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"GenericRedisCacher-full-integration-test.js","sourceRoot":"","sources":["../../src/__integration-tests__/GenericRedisCacher-full-integration-test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|