@expo/entity-cache-adapter-redis 0.31.1 → 0.33.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.
Files changed (47) hide show
  1. package/README.md +2 -3
  2. package/build/GenericRedisCacher.d.ts +11 -0
  3. package/build/GenericRedisCacher.js +6 -0
  4. package/build/GenericRedisCacher.js.map +1 -1
  5. package/build/RedisCacheAdapterProvider.d.ts +4 -4
  6. package/build/RedisCacheAdapterProvider.js +3 -2
  7. package/build/RedisCacheAdapterProvider.js.map +1 -1
  8. package/build/RedisCommon.js +1 -1
  9. package/build/RedisCommon.js.map +1 -1
  10. package/build/__integration-tests__/BatchedRedisCacheAdapter-integration-test.js +10 -11
  11. package/build/__integration-tests__/BatchedRedisCacheAdapter-integration-test.js.map +1 -1
  12. package/build/__integration-tests__/{RedisCacheAdapter-integration-test.js → GenericRedisCacher-full-integration-test.js} +20 -22
  13. package/build/__integration-tests__/GenericRedisCacher-full-integration-test.js.map +1 -0
  14. package/build/__integration-tests__/GenericRedisCacher-integration-test.js +11 -25
  15. package/build/__integration-tests__/GenericRedisCacher-integration-test.js.map +1 -1
  16. package/build/__integration-tests__/errors-test.js +5 -6
  17. package/build/__integration-tests__/errors-test.js.map +1 -1
  18. package/build/__tests__/{RedisCacheAdapter-test.js → GenericRedisCacher-test.js} +35 -35
  19. package/build/__tests__/GenericRedisCacher-test.js.map +1 -0
  20. package/build/index.d.ts +0 -2
  21. package/build/index.js +1 -4
  22. package/build/index.js.map +1 -1
  23. package/build/testfixtures/RedisTestEntity.d.ts +2 -2
  24. package/build/testfixtures/RedisTestEntity.js +6 -7
  25. package/build/testfixtures/RedisTestEntity.js.map +1 -1
  26. package/build/testfixtures/createRedisIntegrationTestEntityCompanionProvider.d.ts +2 -2
  27. package/build/testfixtures/createRedisIntegrationTestEntityCompanionProvider.js +2 -2
  28. package/package.json +4 -4
  29. package/src/GenericRedisCacher.ts +28 -0
  30. package/src/RedisCacheAdapterProvider.ts +10 -5
  31. package/src/__integration-tests__/BatchedRedisCacheAdapter-integration-test.ts +17 -15
  32. package/src/__integration-tests__/{RedisCacheAdapter-integration-test.ts → GenericRedisCacher-full-integration-test.ts} +26 -22
  33. package/src/__integration-tests__/GenericRedisCacher-integration-test.ts +12 -27
  34. package/src/__integration-tests__/errors-test.ts +5 -6
  35. package/src/__tests__/GenericRedisCacher-test.ts +193 -0
  36. package/src/index.ts +0 -2
  37. package/src/testfixtures/RedisTestEntity.ts +6 -8
  38. package/src/testfixtures/createRedisIntegrationTestEntityCompanionProvider.ts +3 -3
  39. package/build/RedisCacheAdapter.d.ts +0 -43
  40. package/build/RedisCacheAdapter.js +0 -44
  41. package/build/RedisCacheAdapter.js.map +0 -1
  42. package/build/__integration-tests__/RedisCacheAdapter-integration-test.js.map +0 -1
  43. package/build/__tests__/RedisCacheAdapter-test.js.map +0 -1
  44. package/src/RedisCacheAdapter.ts +0 -124
  45. package/src/__tests__/RedisCacheAdapter-test.ts +0 -169
  46. /package/build/__integration-tests__/{RedisCacheAdapter-integration-test.d.ts → GenericRedisCacher-full-integration-test.d.ts} +0 -0
  47. /package/build/__tests__/{RedisCacheAdapter-test.d.ts → GenericRedisCacher-test.d.ts} +0 -0
@@ -5,7 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const entity_1 = require("@expo/entity");
7
7
  const ts_mockito_1 = require("ts-mockito");
8
- const RedisCacheAdapter_1 = __importDefault(require("../RedisCacheAdapter"));
8
+ const GenericRedisCacher_1 = __importDefault(require("../GenericRedisCacher"));
9
9
  const entityConfiguration = new entity_1.EntityConfiguration({
10
10
  idField: 'id',
11
11
  tableName: 'blah',
@@ -15,39 +15,43 @@ const entityConfiguration = new entity_1.EntityConfiguration({
15
15
  databaseAdapterFlavor: 'postgres',
16
16
  cacheAdapterFlavor: 'redis',
17
17
  });
18
- describe(RedisCacheAdapter_1.default, () => {
18
+ describe(GenericRedisCacher_1.default, () => {
19
19
  describe('loadManyAsync', () => {
20
20
  it('returns appropriate cache results', async () => {
21
21
  const redisResults = new Map();
22
22
  const mockRedisClient = (0, ts_mockito_1.mock)();
23
23
  // need to have one anything() for each element of spread, in this case 3
24
- (0, ts_mockito_1.when)(mockRedisClient.mget((0, ts_mockito_1.anything)(), (0, ts_mockito_1.anything)(), (0, ts_mockito_1.anything)())).thenCall(async (...keys) => keys.map((k) => { var _a; return (_a = redisResults.get(k)) !== null && _a !== void 0 ? _a : null; }));
25
- const cacheAdapter = new RedisCacheAdapter_1.default(entityConfiguration, {
24
+ (0, ts_mockito_1.when)(mockRedisClient.mget((0, ts_mockito_1.anything)(), (0, ts_mockito_1.anything)(), (0, ts_mockito_1.anything)())).thenCall(async (...keys) => keys.map((k) => redisResults.get(k) ?? null));
25
+ const genericCacher = new GenericRedisCacher_1.default({
26
26
  redisClient: (0, ts_mockito_1.instance)(mockRedisClient),
27
27
  makeKeyFn: (...parts) => parts.join(':'),
28
- cacheKeyVersion: 1,
29
28
  cacheKeyPrefix: 'hello-',
30
29
  ttlSecondsPositive: 1,
31
30
  ttlSecondsNegative: 2,
31
+ }, entityConfiguration);
32
+ const cacheKeyWat = genericCacher['makeCacheKey']('id', 'wat');
33
+ const cacheKeyWho = genericCacher['makeCacheKey']('id', 'who');
34
+ const cacheKeyWhy = genericCacher['makeCacheKey']('id', 'why');
35
+ redisResults.set(cacheKeyWat, JSON.stringify({ id: 'wat' }));
36
+ redisResults.set(cacheKeyWho, '');
37
+ const results = await genericCacher.loadManyAsync([cacheKeyWat, cacheKeyWho, cacheKeyWhy]);
38
+ expect(results.get(cacheKeyWat)).toMatchObject({
39
+ status: entity_1.CacheStatus.HIT,
40
+ item: { id: 'wat' },
32
41
  });
33
- redisResults.set(cacheAdapter['makeCacheKey']('id', 'wat'), JSON.stringify({ id: 'wat' }));
34
- redisResults.set(cacheAdapter['makeCacheKey']('id', 'who'), '');
35
- const results = await cacheAdapter.loadManyAsync('id', ['wat', 'who', 'why']);
36
- expect(results.get('wat')).toMatchObject({ status: entity_1.CacheStatus.HIT, item: { id: 'wat' } });
37
- expect(results.get('who')).toMatchObject({ status: entity_1.CacheStatus.NEGATIVE });
38
- expect(results.get('why')).toMatchObject({ status: entity_1.CacheStatus.MISS });
42
+ expect(results.get(cacheKeyWho)).toMatchObject({ status: entity_1.CacheStatus.NEGATIVE });
43
+ expect(results.get(cacheKeyWhy)).toMatchObject({ status: entity_1.CacheStatus.MISS });
39
44
  expect(results.size).toBe(3);
40
45
  });
41
46
  it('returns empty map when passed empty array of fieldValues', async () => {
42
- const cacheAdapter = new RedisCacheAdapter_1.default(entityConfiguration, {
47
+ const genericCacher = new GenericRedisCacher_1.default({
43
48
  redisClient: (0, ts_mockito_1.instance)((0, ts_mockito_1.mock)()),
44
49
  makeKeyFn: (...parts) => parts.join(':'),
45
- cacheKeyVersion: 1,
46
50
  cacheKeyPrefix: 'hello-',
47
51
  ttlSecondsPositive: 1,
48
52
  ttlSecondsNegative: 2,
49
- });
50
- const results = await cacheAdapter.loadManyAsync('id', []);
53
+ }, entityConfiguration);
54
+ const results = await genericCacher.loadManyAsync([]);
51
55
  expect(results).toEqual(new Map());
52
56
  });
53
57
  });
@@ -63,16 +67,15 @@ describe(RedisCacheAdapter_1.default, () => {
63
67
  const pipeline = (0, ts_mockito_1.instance)(mockPipeline);
64
68
  const mockRedisClient = (0, ts_mockito_1.mock)();
65
69
  (0, ts_mockito_1.when)(mockRedisClient.multi()).thenReturn(pipeline);
66
- const cacheAdapter = new RedisCacheAdapter_1.default(entityConfiguration, {
70
+ const genericCacher = new GenericRedisCacher_1.default({
67
71
  redisClient: (0, ts_mockito_1.instance)(mockRedisClient),
68
72
  makeKeyFn: (...parts) => parts.join(':'),
69
- cacheKeyVersion: 1,
70
73
  cacheKeyPrefix: 'hello-',
71
74
  ttlSecondsPositive: 1,
72
75
  ttlSecondsNegative: 2,
73
- });
74
- await cacheAdapter.cacheManyAsync('id', new Map([['wat', { id: 'wat' }]]));
75
- const cacheKey = cacheAdapter['makeCacheKey']('id', 'wat');
76
+ }, entityConfiguration);
77
+ const cacheKey = genericCacher['makeCacheKey']('id', 'wat');
78
+ await genericCacher.cacheManyAsync(new Map([[cacheKey, { id: 'wat' }]]));
76
79
  expect(redisResults.get(cacheKey)).toMatchObject({
77
80
  value: JSON.stringify({ id: 'wat' }),
78
81
  code: 'EX',
@@ -92,16 +95,15 @@ describe(RedisCacheAdapter_1.default, () => {
92
95
  const pipeline = (0, ts_mockito_1.instance)(mockPipeline);
93
96
  const mockRedisClient = (0, ts_mockito_1.mock)();
94
97
  (0, ts_mockito_1.when)(mockRedisClient.multi()).thenReturn(pipeline);
95
- const cacheAdapter = new RedisCacheAdapter_1.default(entityConfiguration, {
98
+ const genericCacher = new GenericRedisCacher_1.default({
96
99
  redisClient: (0, ts_mockito_1.instance)(mockRedisClient),
97
100
  makeKeyFn: (...parts) => parts.join(':'),
98
- cacheKeyVersion: 1,
99
101
  cacheKeyPrefix: 'hello-',
100
102
  ttlSecondsPositive: 1,
101
103
  ttlSecondsNegative: 2,
102
- });
103
- await cacheAdapter.cacheDBMissesAsync('id', ['wat']);
104
- const cacheKey = cacheAdapter['makeCacheKey']('id', 'wat');
104
+ }, entityConfiguration);
105
+ const cacheKey = genericCacher['makeCacheKey']('id', 'wat');
106
+ await genericCacher.cacheDBMissesAsync([cacheKey]);
105
107
  expect(redisResults.get(cacheKey)).toMatchObject({
106
108
  value: '',
107
109
  code: 'EX',
@@ -113,29 +115,27 @@ describe(RedisCacheAdapter_1.default, () => {
113
115
  it('invalidates correctly', async () => {
114
116
  const mockRedisClient = (0, ts_mockito_1.mock)();
115
117
  (0, ts_mockito_1.when)(mockRedisClient.del()).thenResolve(1);
116
- const cacheAdapter = new RedisCacheAdapter_1.default(entityConfiguration, {
118
+ const genericCacher = new GenericRedisCacher_1.default({
117
119
  redisClient: (0, ts_mockito_1.instance)(mockRedisClient),
118
120
  makeKeyFn: (...parts) => parts.join(':'),
119
- cacheKeyVersion: 1,
120
121
  cacheKeyPrefix: 'hello-',
121
122
  ttlSecondsPositive: 1,
122
123
  ttlSecondsNegative: 2,
123
- });
124
- await cacheAdapter.invalidateManyAsync('id', ['wat']);
125
- const cacheKey = cacheAdapter['makeCacheKey']('id', 'wat');
124
+ }, entityConfiguration);
125
+ const cacheKey = genericCacher['makeCacheKey']('id', 'wat');
126
+ await genericCacher.invalidateManyAsync([cacheKey]);
126
127
  (0, ts_mockito_1.verify)(mockRedisClient.del(cacheKey)).once();
127
128
  });
128
129
  it('returns when passed empty array of fieldValues', async () => {
129
- const cacheAdapter = new RedisCacheAdapter_1.default(entityConfiguration, {
130
+ const genericCacher = new GenericRedisCacher_1.default({
130
131
  redisClient: (0, ts_mockito_1.instance)((0, ts_mockito_1.mock)()),
131
132
  makeKeyFn: (...parts) => parts.join(':'),
132
- cacheKeyVersion: 1,
133
133
  cacheKeyPrefix: 'hello-',
134
134
  ttlSecondsPositive: 1,
135
135
  ttlSecondsNegative: 2,
136
- });
137
- await cacheAdapter.invalidateManyAsync('id', []);
136
+ }, entityConfiguration);
137
+ await genericCacher.invalidateManyAsync([]);
138
138
  });
139
139
  });
140
140
  });
141
- //# sourceMappingURL=RedisCacheAdapter-test.js.map
141
+ //# sourceMappingURL=GenericRedisCacher-test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GenericRedisCacher-test.js","sourceRoot":"","sources":["../../src/__tests__/GenericRedisCacher-test.ts"],"names":[],"mappings":"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"}
package/build/index.d.ts CHANGED
@@ -2,8 +2,6 @@
2
2
  * @packageDocumentation
3
3
  * @module @expo/entity-cache-adapter-redis
4
4
  */
5
- export { default as RedisCacheAdapter } from './RedisCacheAdapter';
6
- export * from './RedisCacheAdapter';
7
5
  export { default as RedisCacheAdapterProvider } from './RedisCacheAdapterProvider';
8
6
  export * from './RedisCommon';
9
7
  export { default as GenericRedisCacher } from './GenericRedisCacher';
package/build/index.js CHANGED
@@ -22,10 +22,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
22
22
  return (mod && mod.__esModule) ? mod : { "default": mod };
23
23
  };
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
- exports.GenericRedisCacher = exports.RedisCacheAdapterProvider = exports.RedisCacheAdapter = void 0;
26
- var RedisCacheAdapter_1 = require("./RedisCacheAdapter");
27
- Object.defineProperty(exports, "RedisCacheAdapter", { enumerable: true, get: function () { return __importDefault(RedisCacheAdapter_1).default; } });
28
- __exportStar(require("./RedisCacheAdapter"), exports);
25
+ exports.GenericRedisCacher = exports.RedisCacheAdapterProvider = void 0;
29
26
  var RedisCacheAdapterProvider_1 = require("./RedisCacheAdapterProvider");
30
27
  Object.defineProperty(exports, "RedisCacheAdapterProvider", { enumerable: true, get: function () { return __importDefault(RedisCacheAdapterProvider_1).default; } });
31
28
  __exportStar(require("./RedisCommon"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,iCAAiC;AACjC;;;GAGG;;;;;;;;;;;;;;;;;;;;AAEH,yDAAmE;AAA1D,uIAAA,OAAO,OAAqB;AACrC,sDAAoC;AACpC,yEAAmF;AAA1E,uJAAA,OAAO,OAA6B;AAC7C,gDAA8B;AAC9B,2DAAqE;AAA5D,yIAAA,OAAO,OAAsB;AACtC,uDAAqC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,iCAAiC;AACjC;;;GAGG;;;;;;;;;;;;;;;;;;;;AAEH,yEAAmF;AAA1E,uJAAA,OAAO,OAA6B;AAC7C,gDAA8B;AAC9B,2DAAqE;AAA5D,yIAAA,OAAO,OAAsB;AACtC,uDAAqC"}
@@ -1,11 +1,11 @@
1
1
  import { AlwaysAllowPrivacyPolicyRule, EntityPrivacyPolicy, ViewerContext, EntityConfiguration, EntityCompanionDefinition, Entity } from '@expo/entity';
2
- export declare type RedisTestEntityFields = {
2
+ export type RedisTestEntityFields = {
3
3
  id: string;
4
4
  name: string;
5
5
  dateField: Date | null;
6
6
  };
7
7
  export default class RedisTestEntity extends Entity<RedisTestEntityFields, string, ViewerContext> {
8
- static getCompanionDefinition(): EntityCompanionDefinition<RedisTestEntityFields, string, ViewerContext, RedisTestEntity, RedisTestEntityPrivacyPolicy>;
8
+ static defineCompanionDefinition(): EntityCompanionDefinition<RedisTestEntityFields, string, ViewerContext, RedisTestEntity, RedisTestEntityPrivacyPolicy>;
9
9
  }
10
10
  export declare class RedisTestEntityPrivacyPolicy extends EntityPrivacyPolicy<RedisTestEntityFields, string, ViewerContext, RedisTestEntity> {
11
11
  protected readonly createRules: AlwaysAllowPrivacyPolicyRule<RedisTestEntityFields, string, ViewerContext, RedisTestEntity, keyof RedisTestEntityFields>[];
@@ -3,8 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.redisTestEntityConfiguration = exports.RedisTestEntityPrivacyPolicy = void 0;
4
4
  const entity_1 = require("@expo/entity");
5
5
  class RedisTestEntity extends entity_1.Entity {
6
- static getCompanionDefinition() {
7
- return redisTestEntityCompanionDefinition;
6
+ static defineCompanionDefinition() {
7
+ return {
8
+ entityClass: RedisTestEntity,
9
+ entityConfiguration: exports.redisTestEntityConfiguration,
10
+ privacyPolicyClass: RedisTestEntityPrivacyPolicy,
11
+ };
8
12
  }
9
13
  }
10
14
  exports.default = RedisTestEntity;
@@ -45,9 +49,4 @@ exports.redisTestEntityConfiguration = new entity_1.EntityConfiguration({
45
49
  databaseAdapterFlavor: 'postgres',
46
50
  cacheAdapterFlavor: 'redis',
47
51
  });
48
- const redisTestEntityCompanionDefinition = new entity_1.EntityCompanionDefinition({
49
- entityClass: RedisTestEntity,
50
- entityConfiguration: exports.redisTestEntityConfiguration,
51
- privacyPolicyClass: RedisTestEntityPrivacyPolicy,
52
- });
53
52
  //# sourceMappingURL=RedisTestEntity.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"RedisTestEntity.js","sourceRoot":"","sources":["../../src/testfixtures/RedisTestEntity.ts"],"names":[],"mappings":";;;AAAA,yCAUsB;AAQtB,MAAqB,eAAgB,SAAQ,eAAoD;IAC/F,MAAM,CAAC,sBAAsB;QAO3B,OAAO,kCAAkC,CAAC;IAC5C,CAAC;CACF;AAVD,kCAUC;AAED,MAAa,4BAA6B,SAAQ,4BAKjD;IALD;;QAM8B,gBAAW,GAAG;YACxC,IAAI,qCAA4B,EAK7B;SACJ,CAAC;QAC0B,cAAS,GAAG;YACtC,IAAI,qCAA4B,EAK7B;SACJ,CAAC;QAC0B,gBAAW,GAAG;YACxC,IAAI,qCAA4B,EAK7B;SACJ,CAAC;QAC0B,gBAAW,GAAG;YACxC,IAAI,qCAA4B,EAK7B;SACJ,CAAC;IACJ,CAAC;CAAA;AAtCD,oEAsCC;AAEY,QAAA,4BAA4B,GAAG,IAAI,4BAAmB,CAAwB;IACzF,OAAO,EAAE,IAAI;IACb,SAAS,EAAE,qBAAqB;IAChC,MAAM,EAAE;QACN,EAAE,EAAE,IAAI,kBAAS,CAAC;YAChB,UAAU,EAAE,IAAI;YAChB,KAAK,EAAE,IAAI;SACZ,CAAC;QACF,IAAI,EAAE,IAAI,oBAAW,CAAC;YACpB,UAAU,EAAE,MAAM;YAClB,KAAK,EAAE,IAAI;SACZ,CAAC;QACF,SAAS,EAAE,IAAI,kBAAS,CAAC;YACvB,UAAU,EAAE,YAAY;SACzB,CAAC;KACH;IACD,qBAAqB,EAAE,UAAU;IACjC,kBAAkB,EAAE,OAAO;CAC5B,CAAC,CAAC;AAEH,MAAM,kCAAkC,GAAG,IAAI,kCAAyB,CAAC;IACvE,WAAW,EAAE,eAAe;IAC5B,mBAAmB,EAAE,oCAA4B;IACjD,kBAAkB,EAAE,4BAA4B;CACjD,CAAC,CAAC"}
1
+ {"version":3,"file":"RedisTestEntity.js","sourceRoot":"","sources":["../../src/testfixtures/RedisTestEntity.ts"],"names":[],"mappings":";;;AAAA,yCAUsB;AAQtB,MAAqB,eAAgB,SAAQ,eAAoD;IAC/F,MAAM,CAAC,yBAAyB;QAO9B,OAAO;YACL,WAAW,EAAE,eAAe;YAC5B,mBAAmB,EAAE,oCAA4B;YACjD,kBAAkB,EAAE,4BAA4B;SACjD,CAAC;IACJ,CAAC;CACF;AAdD,kCAcC;AAED,MAAa,4BAA6B,SAAQ,4BAKjD;IALD;;QAM8B,gBAAW,GAAG;YACxC,IAAI,qCAA4B,EAK7B;SACJ,CAAC;QAC0B,cAAS,GAAG;YACtC,IAAI,qCAA4B,EAK7B;SACJ,CAAC;QAC0B,gBAAW,GAAG;YACxC,IAAI,qCAA4B,EAK7B;SACJ,CAAC;QAC0B,gBAAW,GAAG;YACxC,IAAI,qCAA4B,EAK7B;SACJ,CAAC;IACJ,CAAC;CAAA;AAtCD,oEAsCC;AAEY,QAAA,4BAA4B,GAAG,IAAI,4BAAmB,CAAwB;IACzF,OAAO,EAAE,IAAI;IACb,SAAS,EAAE,qBAAqB;IAChC,MAAM,EAAE;QACN,EAAE,EAAE,IAAI,kBAAS,CAAC;YAChB,UAAU,EAAE,IAAI;YAChB,KAAK,EAAE,IAAI;SACZ,CAAC;QACF,IAAI,EAAE,IAAI,oBAAW,CAAC;YACpB,UAAU,EAAE,MAAM;YAClB,KAAK,EAAE,IAAI;SACZ,CAAC;QACF,SAAS,EAAE,IAAI,kBAAS,CAAC;YACvB,UAAU,EAAE,YAAY;SACzB,CAAC;KACH;IACD,qBAAqB,EAAE,UAAU;IACjC,kBAAkB,EAAE,OAAO;CAC5B,CAAC,CAAC"}
@@ -1,3 +1,3 @@
1
1
  import { IEntityMetricsAdapter, EntityCompanionProvider } from '@expo/entity';
2
- import { RedisCacheAdapterContext } from '../RedisCacheAdapter';
3
- export declare const createRedisIntegrationTestEntityCompanionProvider: (redisCacheAdapterContext: RedisCacheAdapterContext, metricsAdapter?: IEntityMetricsAdapter) => EntityCompanionProvider;
2
+ import { GenericRedisCacheContext } from '../GenericRedisCacher';
3
+ export declare const createRedisIntegrationTestEntityCompanionProvider: (genericRedisCacheContext: GenericRedisCacheContext, metricsAdapter?: IEntityMetricsAdapter) => EntityCompanionProvider;
@@ -8,7 +8,7 @@ const entity_1 = require("@expo/entity");
8
8
  const RedisCacheAdapterProvider_1 = __importDefault(require("../RedisCacheAdapterProvider"));
9
9
  // share across all in calls in test to simulate postgres
10
10
  const adapterProvider = new entity_1.StubDatabaseAdapterProvider();
11
- const createRedisIntegrationTestEntityCompanionProvider = (redisCacheAdapterContext, metricsAdapter = new entity_1.NoOpEntityMetricsAdapter()) => {
11
+ const createRedisIntegrationTestEntityCompanionProvider = (genericRedisCacheContext, metricsAdapter = new entity_1.NoOpEntityMetricsAdapter()) => {
12
12
  return new entity_1.EntityCompanionProvider(metricsAdapter, new Map([
13
13
  [
14
14
  'postgres',
@@ -21,7 +21,7 @@ const createRedisIntegrationTestEntityCompanionProvider = (redisCacheAdapterCont
21
21
  [
22
22
  'redis',
23
23
  {
24
- cacheAdapterProvider: new RedisCacheAdapterProvider_1.default(redisCacheAdapterContext),
24
+ cacheAdapterProvider: new RedisCacheAdapterProvider_1.default(genericRedisCacheContext),
25
25
  },
26
26
  ],
27
27
  ]));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expo/entity-cache-adapter-redis",
3
- "version": "0.31.1",
3
+ "version": "0.33.0",
4
4
  "description": "Redis cache adapter for @expo/entity",
5
5
  "files": [
6
6
  "build",
@@ -19,7 +19,7 @@
19
19
  "barrelsby": "barrelsby --directory src --location top --exclude tests__ --singleQuotes --exportDefault --delete"
20
20
  },
21
21
  "engines": {
22
- "node": ">=12"
22
+ "node": ">=16"
23
23
  },
24
24
  "keywords": [
25
25
  "entity"
@@ -31,8 +31,8 @@
31
31
  "ioredis": ">=5"
32
32
  },
33
33
  "devDependencies": {
34
- "@expo/entity": "^0.31.1",
34
+ "@expo/entity": "^0.33.0",
35
35
  "ioredis": "^5.2.5"
36
36
  },
37
- "gitHead": "83fe9cdea5b0cd69f38ac58eed12e96d5fa51d07"
37
+ "gitHead": "659e08386f2c5e33e9ac4c670fd832a62a2b6382"
38
38
  }
@@ -6,6 +6,7 @@ import {
6
6
  transformFieldsToCacheObject,
7
7
  IEntityGenericCacher,
8
8
  } from '@expo/entity';
9
+ import invariant from 'invariant';
9
10
 
10
11
  import { redisTransformerMap } from './RedisCommon';
11
12
  import wrapNativeRedisCallAsync from './errors/wrapNativeRedisCallAsync';
@@ -31,6 +32,18 @@ export interface GenericRedisCacheContext {
31
32
  */
32
33
  redisClient: IRedis;
33
34
 
35
+ /**
36
+ * Create a key string for key parts (cache key prefix, versions, entity name, etc).
37
+ * Most commonly a simple `parts.join(':')`. See integration test for example.
38
+ */
39
+ makeKeyFn: (...parts: string[]) => string;
40
+
41
+ /**
42
+ * Prefix prepended to all entity cache keys. Useful for adding a short, human-readable
43
+ * distintion for entity keys, e.g. `ent-`
44
+ */
45
+ cacheKeyPrefix: string;
46
+
34
47
  /**
35
48
  * TTL for caching database hits. Successive entity loads within this TTL
36
49
  * will be read from cache (unless invalidated).
@@ -131,4 +144,19 @@ export default class GenericRedisCacher<TFields> implements IEntityGenericCacher
131
144
 
132
145
  await wrapNativeRedisCallAsync(() => this.context.redisClient.del(...keys));
133
146
  }
147
+
148
+ public makeCacheKey<N extends keyof TFields>(
149
+ fieldName: N,
150
+ fieldValue: NonNullable<TFields[N]>
151
+ ): string {
152
+ const columnName = this.entityConfiguration.entityToDBFieldsKeyMapping.get(fieldName);
153
+ invariant(columnName, `database field mapping missing for ${String(fieldName)}`);
154
+ return this.context.makeKeyFn(
155
+ this.context.cacheKeyPrefix,
156
+ this.entityConfiguration.tableName,
157
+ `v2.${this.entityConfiguration.cacheKeyVersion}`,
158
+ columnName,
159
+ String(fieldValue)
160
+ );
161
+ }
134
162
  }
@@ -1,13 +1,18 @@
1
- import { IEntityCacheAdapterProvider, EntityConfiguration, EntityCacheAdapter } from '@expo/entity';
1
+ import {
2
+ IEntityCacheAdapterProvider,
3
+ EntityConfiguration,
4
+ IEntityCacheAdapter,
5
+ GenericEntityCacheAdapter,
6
+ } from '@expo/entity';
2
7
 
3
- import RedisCacheAdapter, { RedisCacheAdapterContext } from './RedisCacheAdapter';
8
+ import GenericRedisCacher, { GenericRedisCacheContext } from './GenericRedisCacher';
4
9
 
5
10
  export default class RedisCacheAdapterProvider implements IEntityCacheAdapterProvider {
6
- constructor(private readonly context: RedisCacheAdapterContext) {}
11
+ constructor(private readonly context: GenericRedisCacheContext) {}
7
12
 
8
13
  getCacheAdapter<TFields>(
9
14
  entityConfiguration: EntityConfiguration<TFields>
10
- ): EntityCacheAdapter<TFields> {
11
- return new RedisCacheAdapter(entityConfiguration, this.context);
15
+ ): IEntityCacheAdapter<TFields> {
16
+ return new GenericEntityCacheAdapter(new GenericRedisCacher(this.context, entityConfiguration));
12
17
  }
13
18
  }
@@ -6,8 +6,11 @@ import nullthrows from 'nullthrows';
6
6
  import { URL } from 'url';
7
7
  import { v4 as uuidv4 } from 'uuid';
8
8
 
9
- import { IRedis, IRedisTransaction } from '../GenericRedisCacher';
10
- import RedisCacheAdapter, { RedisCacheAdapterContext } from '../RedisCacheAdapter';
9
+ import GenericRedisCacher, {
10
+ IRedis,
11
+ IRedisTransaction,
12
+ GenericRedisCacheContext,
13
+ } from '../GenericRedisCacher';
11
14
  import RedisTestEntity from '../testfixtures/RedisTestEntity';
12
15
  import { createRedisIntegrationTestEntityCompanionProvider } from '../testfixtures/createRedisIntegrationTestEntityCompanionProvider';
13
16
 
@@ -54,14 +57,14 @@ class BatchedRedis implements IRedis {
54
57
  }
55
58
  }
56
59
 
57
- describe(RedisCacheAdapter, () => {
60
+ describe(GenericRedisCacher, () => {
58
61
  const redis = new Redis(new URL(process.env['REDIS_URL']!).toString());
59
62
  const redisClient = new BatchedRedis(redis);
60
63
 
61
- let redisCacheAdapterContext: RedisCacheAdapterContext;
64
+ let genericRedisCacheContext: GenericRedisCacheContext;
62
65
 
63
66
  beforeAll(() => {
64
- redisCacheAdapterContext = {
67
+ genericRedisCacheContext = {
65
68
  redisClient,
66
69
  makeKeyFn(...parts: string[]): string {
67
70
  const delimiter = ':';
@@ -71,7 +74,6 @@ describe(RedisCacheAdapter, () => {
71
74
  return escapedParts.join(delimiter);
72
75
  },
73
76
  cacheKeyPrefix: 'test-',
74
- cacheKeyVersion: 1,
75
77
  ttlSecondsPositive: 86400, // 1 day
76
78
  ttlSecondsNegative: 600, // 10 minutes
77
79
  };
@@ -88,16 +90,16 @@ describe(RedisCacheAdapter, () => {
88
90
  it('has correct caching behavior', async () => {
89
91
  // simulate two requests
90
92
  const viewerContext = new ViewerContext(
91
- createRedisIntegrationTestEntityCompanionProvider(redisCacheAdapterContext)
93
+ createRedisIntegrationTestEntityCompanionProvider(genericRedisCacheContext)
92
94
  );
93
95
 
94
96
  const mgetSpy = jest.spyOn(redis, 'mget');
95
97
 
96
- const cacheAdapter = viewerContext.entityCompanionProvider.getCompanionForEntity(
97
- RedisTestEntity,
98
- RedisTestEntity.getCompanionDefinition()
99
- )['tableDataCoordinator']['cacheAdapter'];
100
- const cacheKeyMaker = cacheAdapter['makeCacheKey'].bind(cacheAdapter);
98
+ const genericCacher =
99
+ viewerContext.entityCompanionProvider.getCompanionForEntity(RedisTestEntity)[
100
+ 'tableDataCoordinator'
101
+ ]['cacheAdapter']['genericCacher'];
102
+ const cacheKeyMaker = genericCacher['makeCacheKey'].bind(genericCacher);
101
103
 
102
104
  const entity1Created = await RedisTestEntity.creator(viewerContext)
103
105
  .setField('name', 'blah')
@@ -106,13 +108,13 @@ describe(RedisCacheAdapter, () => {
106
108
  // loading an entity should put it in cache. load by multiple requests and multiple fields in same tick to ensure batch works
107
109
  mgetSpy.mockClear();
108
110
  const viewerContext1 = new ViewerContext(
109
- createRedisIntegrationTestEntityCompanionProvider(redisCacheAdapterContext)
111
+ createRedisIntegrationTestEntityCompanionProvider(genericRedisCacheContext)
110
112
  );
111
113
  const viewerContext2 = new ViewerContext(
112
- createRedisIntegrationTestEntityCompanionProvider(redisCacheAdapterContext)
114
+ createRedisIntegrationTestEntityCompanionProvider(genericRedisCacheContext)
113
115
  );
114
116
  const viewerContext3 = new ViewerContext(
115
- createRedisIntegrationTestEntityCompanionProvider(redisCacheAdapterContext)
117
+ createRedisIntegrationTestEntityCompanionProvider(genericRedisCacheContext)
116
118
  );
117
119
  const [entity1, entity2, entity3] = await Promise.all([
118
120
  RedisTestEntity.loader(viewerContext1).enforcing().loadByIDAsync(entity1Created.getID()),
@@ -4,19 +4,18 @@ import Redis from 'ioredis';
4
4
  import { URL } from 'url';
5
5
  import { v4 as uuidv4 } from 'uuid';
6
6
 
7
- import RedisCacheAdapter, { RedisCacheAdapterContext } from '../RedisCacheAdapter';
7
+ import GenericRedisCacher, { GenericRedisCacheContext } from '../GenericRedisCacher';
8
8
  import RedisTestEntity from '../testfixtures/RedisTestEntity';
9
9
  import { createRedisIntegrationTestEntityCompanionProvider } from '../testfixtures/createRedisIntegrationTestEntityCompanionProvider';
10
10
 
11
11
  class TestViewerContext extends ViewerContext {}
12
12
 
13
- describe(RedisCacheAdapter, () => {
14
- const redisClient = new Redis(new URL(process.env['REDIS_URL']!).toString());
15
- let redisCacheAdapterContext: RedisCacheAdapterContext;
13
+ describe(GenericRedisCacher, () => {
14
+ let genericRedisCacheContext: GenericRedisCacheContext;
16
15
 
17
16
  beforeAll(() => {
18
- redisCacheAdapterContext = {
19
- redisClient,
17
+ genericRedisCacheContext = {
18
+ redisClient: new Redis(new URL(process.env['REDIS_URL']!).toString()),
20
19
  makeKeyFn(...parts: string[]): string {
21
20
  const delimiter = ':';
22
21
  const escapedParts = parts.map((part) =>
@@ -25,28 +24,27 @@ describe(RedisCacheAdapter, () => {
25
24
  return escapedParts.join(delimiter);
26
25
  },
27
26
  cacheKeyPrefix: 'test-',
28
- cacheKeyVersion: 1,
29
27
  ttlSecondsPositive: 86400, // 1 day
30
28
  ttlSecondsNegative: 600, // 10 minutes
31
29
  };
32
30
  });
33
31
 
34
32
  beforeEach(async () => {
35
- await redisClient.flushdb();
33
+ await (genericRedisCacheContext.redisClient as Redis).flushdb();
36
34
  });
37
35
  afterAll(async () => {
38
- redisClient.disconnect();
36
+ (genericRedisCacheContext.redisClient as Redis).disconnect();
39
37
  });
40
38
 
41
39
  it('has correct caching behavior', async () => {
42
40
  const viewerContext = new TestViewerContext(
43
- createRedisIntegrationTestEntityCompanionProvider(redisCacheAdapterContext)
41
+ createRedisIntegrationTestEntityCompanionProvider(genericRedisCacheContext)
44
42
  );
45
- const cacheAdapter = viewerContext.entityCompanionProvider.getCompanionForEntity(
46
- RedisTestEntity,
47
- RedisTestEntity.getCompanionDefinition()
48
- )['tableDataCoordinator']['cacheAdapter'];
49
- const cacheKeyMaker = cacheAdapter['makeCacheKey'].bind(cacheAdapter);
43
+ const genericCacher =
44
+ viewerContext.entityCompanionProvider.getCompanionForEntity(RedisTestEntity)[
45
+ 'tableDataCoordinator'
46
+ ]['cacheAdapter']['genericCacher'];
47
+ const cacheKeyMaker = genericCacher['makeCacheKey'].bind(genericCacher);
50
48
 
51
49
  const entity1Created = await RedisTestEntity.creator(viewerContext)
52
50
  .setField('name', 'blah')
@@ -57,7 +55,9 @@ describe(RedisCacheAdapter, () => {
57
55
  .enforcing()
58
56
  .loadByIDAsync(entity1Created.getID());
59
57
 
60
- const cachedJSON = await redisClient.get(cacheKeyMaker('id', entity1.getID()));
58
+ const cachedJSON = await (genericRedisCacheContext.redisClient as Redis).get(
59
+ cacheKeyMaker('id', entity1.getID())
60
+ );
61
61
  const cachedValue = JSON.parse(cachedJSON!);
62
62
  expect(cachedValue).toMatchObject({
63
63
  id: entity1.getID(),
@@ -72,7 +72,9 @@ describe(RedisCacheAdapter, () => {
72
72
  );
73
73
  expect(entityNonExistentResult.ok).toBe(false);
74
74
 
75
- const nonExistentCachedValue = await redisClient.get(cacheKeyMaker('id', nonExistentId));
75
+ const nonExistentCachedValue = await (genericRedisCacheContext.redisClient as Redis).get(
76
+ cacheKeyMaker('id', nonExistentId)
77
+ );
76
78
  expect(nonExistentCachedValue).toEqual('');
77
79
 
78
80
  // load again through entities framework to ensure it reads negative result
@@ -83,13 +85,15 @@ describe(RedisCacheAdapter, () => {
83
85
 
84
86
  // invalidate from cache to ensure it invalidates correctly
85
87
  await RedisTestEntity.loader(viewerContext).invalidateFieldsAsync(entity1.getAllFields());
86
- const cachedValueNull = await redisClient.get(cacheKeyMaker('id', entity1.getID()));
88
+ const cachedValueNull = await (genericRedisCacheContext.redisClient as Redis).get(
89
+ cacheKeyMaker('id', entity1.getID())
90
+ );
87
91
  expect(cachedValueNull).toBe(null);
88
92
  });
89
93
 
90
94
  it('caches and restores date fields', async () => {
91
95
  const viewerContext = new TestViewerContext(
92
- createRedisIntegrationTestEntityCompanionProvider(redisCacheAdapterContext)
96
+ createRedisIntegrationTestEntityCompanionProvider(genericRedisCacheContext)
93
97
  );
94
98
  const date = new Date();
95
99
  const entity1 = await enforceAsyncResult(
@@ -104,7 +108,7 @@ describe(RedisCacheAdapter, () => {
104
108
 
105
109
  // simulate new request
106
110
  const vc2 = new TestViewerContext(
107
- createRedisIntegrationTestEntityCompanionProvider(redisCacheAdapterContext)
111
+ createRedisIntegrationTestEntityCompanionProvider(genericRedisCacheContext)
108
112
  );
109
113
  const entity3 = await RedisTestEntity.loader(vc2).enforcing().loadByIDAsync(entity1.getID());
110
114
  expect(entity3.getField('dateField')).toEqual(date);
@@ -112,7 +116,7 @@ describe(RedisCacheAdapter, () => {
112
116
 
113
117
  it('caches and restores empty string field keys', async () => {
114
118
  const viewerContext = new TestViewerContext(
115
- createRedisIntegrationTestEntityCompanionProvider(redisCacheAdapterContext)
119
+ createRedisIntegrationTestEntityCompanionProvider(genericRedisCacheContext)
116
120
  );
117
121
  const entity1 = await enforceAsyncResult(
118
122
  RedisTestEntity.creator(viewerContext).setField('name', '').createAsync()
@@ -124,7 +128,7 @@ describe(RedisCacheAdapter, () => {
124
128
 
125
129
  // simulate new request
126
130
  const vc2 = new TestViewerContext(
127
- createRedisIntegrationTestEntityCompanionProvider(redisCacheAdapterContext)
131
+ createRedisIntegrationTestEntityCompanionProvider(genericRedisCacheContext)
128
132
  );
129
133
  const entity3 = await RedisTestEntity.loader(vc2)
130
134
  .enforcing()