cachette 4.0.12 → 4.0.14

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.
@@ -3,11 +3,10 @@ import { LRUCache } from 'lru-cache';
3
3
  import { CachableValue, CacheInstance } from './CacheInstance';
4
4
 
5
5
  async function sleep(ms: number): Promise<void> {
6
- return new Promise(resolve => setTimeout(resolve, ms));
6
+ return new Promise((resolve) => setTimeout(resolve, ms));
7
7
  }
8
8
 
9
9
  export class LocalCache extends CacheInstance {
10
-
11
10
  public static DEFAULT_MAX_ITEMS = 5000;
12
11
  // Default maximum age for the items, in MS.
13
12
  public static DEFAULT_MAX_AGE: number = 30 * 60 * 1000;
@@ -126,12 +125,12 @@ export class LocalCache extends CacheInstance {
126
125
  */
127
126
  public async lock(resource: string, ttlMs: number): Promise<any> {
128
127
  let isLocked = true;
129
- const startTimestamp = Date.now()
130
- while(isLocked) {
128
+ const startTimestamp = Date.now();
129
+ while (isLocked) {
131
130
  if (Date.now() - startTimestamp > LocalCache.LOCK_ACQUIRE_TIMEOUT) {
132
- throw new Error(`Abandoning locking ${resource} , as timed out while waiting for other lock to be released.`)
131
+ throw new Error(`Abandoning locking ${resource} , as timed out while waiting for other lock to be released.`);
133
132
  }
134
- this.cache.purgeStale()
133
+ this.cache.purgeStale();
135
134
  if (!this.cache.has(resource)) {
136
135
  isLocked = false;
137
136
  } else {
@@ -141,7 +140,9 @@ export class LocalCache extends CacheInstance {
141
140
  }
142
141
  }
143
142
  this.cache.set(resource, 1, { ttl: ttlMs });
144
- return new Promise(resolve => { resolve(resource) });
143
+ return new Promise((resolve) => {
144
+ resolve(resource);
145
+ });
145
146
  }
146
147
 
147
148
  /**
@@ -149,7 +150,9 @@ export class LocalCache extends CacheInstance {
149
150
  */
150
151
  public async unlock(lock: any): Promise<void> {
151
152
  this.cache.delete(lock);
152
- return new Promise(resolve => { resolve() });
153
+ return new Promise((resolve) => {
154
+ resolve();
155
+ });
153
156
  }
154
157
 
155
158
  /**
@@ -172,7 +175,8 @@ export class LocalCache extends CacheInstance {
172
175
  found = true;
173
176
  }
174
177
  });
175
- return new Promise((resolve) => { resolve(found) });
178
+ return new Promise((resolve) => {
179
+ resolve(found);
180
+ });
176
181
  }
177
-
178
182
  }
@@ -18,7 +18,6 @@ export interface Lock {
18
18
  * or the process might crash unexpectedly.
19
19
  */
20
20
  export class RedisCache extends CacheInstance {
21
-
22
21
  /**
23
22
  * We cannot store null and booleans in Redis, so we store
24
23
  * random values representing these values instead.
@@ -66,13 +65,15 @@ export class RedisCache extends CacheInstance {
66
65
  // This prevents get/setValue calls from hanging if there is no active connection
67
66
  enableOfflineQueue: false,
68
67
  });
69
- this.redlock = new Redlock([this.redisClient as unknown as Redlock.CompatibleRedisClient], { // Hack until Redlock 5.x is out of beta
68
+ this.redlock = new Redlock([this.redisClient as unknown as Redlock.CompatibleRedisClient], {
69
+ // Hack until Redlock 5.x is out of beta
70
70
  driftFactor: RedisCache.REDLOCK_CLOCK_DRIFT_FACTOR,
71
71
  retryCount: RedisCache.REDLOCK_RETRY_COUNT,
72
72
  retryDelay: RedisCache.REDLOCK_RETRY_DELAY_MS,
73
73
  retryJitter: RedisCache.REDLOCK_JITTER_MS,
74
74
  });
75
- this.redlockWithoutRetry = new Redlock([this.redisClient as unknown as Redlock.CompatibleRedisClient], { // Hack until Redlock 5.x is out of beta
75
+ this.redlockWithoutRetry = new Redlock([this.redisClient as unknown as Redlock.CompatibleRedisClient], {
76
+ // Hack until Redlock 5.x is out of beta
76
77
  driftFactor: RedisCache.REDLOCK_CLOCK_DRIFT_FACTOR,
77
78
  retryCount: 0,
78
79
  retryDelay: 0,
@@ -95,7 +96,7 @@ export class RedisCache extends CacheInstance {
95
96
  if (this.ready) {
96
97
  return;
97
98
  }
98
- return new Promise<void>(resolve => this.redisClient.on('ready', resolve));
99
+ return new Promise<void>((resolve) => this.redisClient.on('ready', resolve));
99
100
  }
100
101
 
101
102
  /**
@@ -147,7 +148,6 @@ export class RedisCache extends CacheInstance {
147
148
  *
148
149
  */
149
150
  public static serializeValue(value: CachableValue): string {
150
-
151
151
  if (value === null) {
152
152
  return RedisCache.NULL_VALUE;
153
153
  }
@@ -161,10 +161,13 @@ export class RedisCache extends CacheInstance {
161
161
  }
162
162
 
163
163
  if (value instanceof Error) {
164
- return RedisCache.ERROR_PREFIX + JSON.stringify({
165
- ...value, // serialize potential Error metadata set as object properties
166
- message: value.message,
167
- });
164
+ return (
165
+ RedisCache.ERROR_PREFIX +
166
+ JSON.stringify({
167
+ ...value, // serialize potential Error metadata set as object properties
168
+ message: value.message,
169
+ })
170
+ );
168
171
  }
169
172
 
170
173
  if (typeof value === 'number') {
@@ -172,15 +175,18 @@ export class RedisCache extends CacheInstance {
172
175
  }
173
176
 
174
177
  if (value instanceof Object) {
175
- return RedisCache.JSON_PREFIX + JSON.stringify(value, (key, value) => {
176
- if (value instanceof Set) {
177
- return { __dataType: 'Set', value: Array.from(value) };
178
- } else if (value instanceof Map) {
179
- return { __dataType: 'Map', value: Array.from(value) };
180
- } else {
181
- return value;
182
- }
183
- });
178
+ return (
179
+ RedisCache.JSON_PREFIX +
180
+ JSON.stringify(value, (key, value) => {
181
+ if (value instanceof Set) {
182
+ return { __dataType: 'Set', value: Array.from(value) };
183
+ } else if (value instanceof Map) {
184
+ return { __dataType: 'Map', value: Array.from(value) };
185
+ } else {
186
+ return value;
187
+ }
188
+ })
189
+ );
184
190
  }
185
191
 
186
192
  return value;
@@ -199,7 +205,6 @@ export class RedisCache extends CacheInstance {
199
205
  *
200
206
  */
201
207
  public static deserializeValue(value: string | null): CachableValue {
202
-
203
208
  if (value === null) {
204
209
  // null means that the key was not present, which we interpret as undefined.
205
210
  return undefined;
@@ -245,34 +250,28 @@ export class RedisCache extends CacheInstance {
245
250
  }
246
251
 
247
252
  return value;
248
-
249
253
  }
250
254
 
251
255
  /**
252
256
  * @inheritdoc
253
257
  */
254
- public async setValue(
255
- key: string,
256
- value: CachableValue,
257
- ttl = 0,
258
- ): Promise<boolean> {
258
+ public async setValue(key: string, value: CachableValue, ttl = 0): Promise<boolean> {
259
259
  try {
260
260
  return await this.setValueInternal(key, value, ttl);
261
261
  } catch (err) {
262
- // Examples of things that may occur here:
263
- // - A timeout, if the connection was broken during a value fetch.
264
- // - A general error, e.g. if Redis is Out Of Memory.
262
+ // Examples of things that may occur here:
263
+ // - A timeout, if the connection was broken during a value fetch.
264
+ // - A general error, e.g. if Redis is Out Of Memory.
265
265
  const error = err as Error;
266
- this.emit('warn', `Error while setting Redis key ${key} with ttl ${ttl}: ${error.name} - ${error.message}\n${error.stack}`);
266
+ this.emit(
267
+ 'warn',
268
+ `Error while setting Redis key ${key} with ttl ${ttl}: ${error.name} - ${error.message}\n${error.stack}`,
269
+ );
267
270
  return false;
268
271
  }
269
272
  }
270
273
 
271
- public async setValueInternal(
272
- key: string,
273
- value: CachableValue,
274
- ttl: number,
275
- ): Promise<boolean> {
274
+ public async setValueInternal(key: string, value: CachableValue, ttl: number): Promise<boolean> {
276
275
  this.emit('set', key, value);
277
276
 
278
277
  if (value === undefined) {
@@ -387,7 +386,7 @@ export class RedisCache extends CacheInstance {
387
386
 
388
387
  return {
389
388
  value: internalLock.value,
390
- unlock: async () => internalLock.unlock()
389
+ unlock: async () => internalLock.unlock(),
391
390
  };
392
391
  }
393
392
 
@@ -420,11 +419,18 @@ export class RedisCache extends CacheInstance {
420
419
  public async hasLock(prefix: string): Promise<boolean> {
421
420
  const redisPrefix = prefix.endsWith('*') ? prefix : `${prefix}*`;
422
421
  let cursor = '';
423
- while (cursor !== '0') { // indicates Redis completed the scan
422
+ while (cursor !== '0') {
423
+ // indicates Redis completed the scan
424
424
  // Redis detail: we set the `count` option to a number (1000) greater than
425
425
  // the default (10), to minimize the amount of network round-trips caused
426
426
  // by incomplete scans needing more scanning from the returned cursor.
427
- const [nextCursor, matchingKeys] = await this.redisClient.scan(cursor || '0', 'MATCH', redisPrefix, 'COUNT', 1000);
427
+ const [nextCursor, matchingKeys] = await this.redisClient.scan(
428
+ cursor || '0',
429
+ 'MATCH',
430
+ redisPrefix,
431
+ 'COUNT',
432
+ 1000,
433
+ );
428
434
  if (matchingKeys.length > 0) {
429
435
  return true;
430
436
  }
@@ -437,5 +443,4 @@ export class RedisCache extends CacheInstance {
437
443
  public async quit(): Promise<void> {
438
444
  await this.redisClient.quit();
439
445
  }
440
-
441
446
  }
@@ -2,7 +2,6 @@ import { CachableValue, CacheInstance } from './CacheInstance';
2
2
  import { RedisCache } from './RedisCache';
3
3
  import { LocalCache } from './LocalCache';
4
4
 
5
-
6
5
  /**
7
6
  * Write-through cache, using Redis and a local LRU cache with aligned TTLs.
8
7
  *
@@ -31,7 +30,6 @@ import { LocalCache } from './LocalCache';
31
30
  * "pub/sub traffic explosion" is a non-concern? To be evaluated :)
32
31
  */
33
32
  export class WriteThroughCache extends CacheInstance {
34
-
35
33
  private redisCacheForWriting: CacheInstance;
36
34
  private redisCacheForReading: CacheInstance;
37
35
  private localCache: CacheInstance;
@@ -59,26 +57,33 @@ export class WriteThroughCache extends CacheInstance {
59
57
  const metricsPeriod = parseInt(process.env.CACHETTE_METRICS_PERIOD_MINUTES, 10);
60
58
  if (Number.isInteger(metricsPeriod) && metricsPeriod > 0) {
61
59
  this.metrics.enabled = true;
62
- this.redisCacheForWriting.emit('info', `WriteThroughCache metrics enabled, will report every ${metricsPeriod} min`);
63
- setInterval(() => {
64
- const total = this.metrics.localHits + this.metrics.redisHits + this.metrics.doubleMisses;
65
- this.redisCacheForWriting.emit(
66
- 'info',
67
- `WriteThroughCache metrics during last ${metricsPeriod} min - Total: ${total}, ` +
68
- `Local hits: ${this.metrics.localHits} (${total && Math.floor(100 * this.metrics.localHits / total)}%), ` +
69
- `Redis hits: ${this.metrics.redisHits} (${total && Math.floor(100 * this.metrics.redisHits / total)}%), ` +
70
- `Double misses: ${this.metrics.doubleMisses} (${total && Math.floor(100 * this.metrics.doubleMisses / total)}%).`,
71
- );
72
-
73
- this.metrics.localHits = 0;
74
- this.metrics.redisHits = 0;
75
- this.metrics.doubleMisses = 0;
76
- }, metricsPeriod * 60 * 1000);
60
+ this.redisCacheForWriting.emit(
61
+ 'info',
62
+ `WriteThroughCache metrics enabled, will report every ${metricsPeriod} min`,
63
+ );
64
+ setInterval(
65
+ () => {
66
+ const total = this.metrics.localHits + this.metrics.redisHits + this.metrics.doubleMisses;
67
+ this.redisCacheForWriting.emit(
68
+ 'info',
69
+ `WriteThroughCache metrics during last ${metricsPeriod} min - Total: ${total}, ` +
70
+ `Local hits: ${this.metrics.localHits} (${total && Math.floor((100 * this.metrics.localHits) / total)}%), ` +
71
+ `Redis hits: ${this.metrics.redisHits} (${total && Math.floor((100 * this.metrics.redisHits) / total)}%), ` +
72
+ `Double misses: ${this.metrics.doubleMisses} (${total && Math.floor((100 * this.metrics.doubleMisses) / total)}%).`,
73
+ );
74
+
75
+ this.metrics.localHits = 0;
76
+ this.metrics.redisHits = 0;
77
+ this.metrics.doubleMisses = 0;
78
+ },
79
+ metricsPeriod * 60 * 1000,
80
+ );
77
81
  } else {
78
82
  this.redisCacheForWriting.emit(
79
83
  'warn',
80
84
  'WriteThroughCache metrics activation impossible, CACHETTE_METRICS_PERIOD_MINUTES is invalid. ' +
81
- `Must be a positive integer, but was ${process.env.CACHETTE_METRICS_PERIOD_MINUTES}`);
85
+ `Must be a positive integer, but was ${process.env.CACHETTE_METRICS_PERIOD_MINUTES}`,
86
+ );
82
87
  }
83
88
  }
84
89
  }
@@ -101,19 +106,15 @@ export class WriteThroughCache extends CacheInstance {
101
106
  * @inheritdoc
102
107
  */
103
108
  public async itemCount(): Promise<number> {
104
- return await this.redisCacheForReading.itemCount() + await this.localCache.itemCount();
109
+ return (await this.redisCacheForReading.itemCount()) + (await this.localCache.itemCount());
105
110
  }
106
111
 
107
112
  /**
108
113
  * @inheritdoc
109
114
  */
110
- public async setValue(
111
- key: string,
112
- value: CachableValue,
113
- ttl = 0,
114
- ): Promise<boolean> {
115
+ public async setValue(key: string, value: CachableValue, ttl = 0): Promise<boolean> {
115
116
  const response = await this.localCache.setValue(key, value, ttl);
116
- return await this.redisCacheForWriting.setValue(key, value, ttl) && response;
117
+ return (await this.redisCacheForWriting.setValue(key, value, ttl)) && response;
117
118
  }
118
119
 
119
120
  /**
@@ -166,7 +167,7 @@ export class WriteThroughCache extends CacheInstance {
166
167
  * @inheritdoc
167
168
  */
168
169
  public async waitForReplication(replicas: number, timeout: number): Promise<number> {
169
- this.emit('wait')
170
+ this.emit('wait');
170
171
  await this.localCache.waitForReplication(replicas, timeout);
171
172
  return this.redisCacheForWriting.waitForReplication(replicas, timeout);
172
173
  }
@@ -196,5 +197,4 @@ export class WriteThroughCache extends CacheInstance {
196
197
  public isLockingSupported(): boolean {
197
198
  return false;
198
199
  }
199
-
200
200
  }
@@ -2,11 +2,8 @@ import { expect } from 'chai';
2
2
  import { CacheClient } from '../src/lib/CacheClient';
3
3
  import { LocalCache } from '../src/lib/LocalCache';
4
4
 
5
-
6
5
  describe('CacheClient', () => {
7
-
8
6
  describe('decorator cached()', () => {
9
-
10
7
  interface Response {
11
8
  variant: string;
12
9
  value: number;
@@ -20,7 +17,7 @@ describe('CacheClient', () => {
20
17
  @CacheClient.cached()
21
18
  async fetchSomething(variant: string): Promise<Response> {
22
19
  this.numCalled++;
23
- await new Promise(resolve => setTimeout(resolve, 100));
20
+ await new Promise((resolve) => setTimeout(resolve, 100));
24
21
  return {
25
22
  variant: variant,
26
23
  value: 100 + parseInt(variant, 10),
@@ -33,7 +30,7 @@ describe('CacheClient', () => {
33
30
  throw new Error('nope');
34
31
  }
35
32
 
36
- @CacheClient.cached(undefined, err => err['retryable'] === false) // custom error-caching function: caches only 'retryable' errors
33
+ @CacheClient.cached(undefined, (err) => err['retryable'] === false) // custom error-caching function: caches only 'retryable' errors
37
34
  async throwingMachine2(): Promise<string> {
38
35
  this.numCalled++;
39
36
  // initially throws a retryable (to assert we don't cache),
@@ -45,10 +42,9 @@ describe('CacheClient', () => {
45
42
  }
46
43
  throw new Error('nope');
47
44
  }
48
-
49
45
  }
50
46
 
51
- it ('1. provides an error-caching function that caches all errors by default, 2. cohabits with the non-caching function', async () => {
47
+ it('1. provides an error-caching function that caches all errors by default, 2. cohabits with the non-caching function', async () => {
52
48
  const myObj = new MyClass();
53
49
  const myObjThrowingMachine1WithErrorCaching = myObj.getErrorCachingFunction('throwingMachine1');
54
50
 
@@ -147,7 +143,7 @@ describe('CacheClient', () => {
147
143
 
148
144
  const results = await Promise.all(jobs);
149
145
  let numSuccess = 0;
150
- results.forEach(x => {
146
+ results.forEach((x) => {
151
147
  if (x.value === 100 + parseInt(x.variant, 10)) {
152
148
  numSuccess++;
153
149
  }
@@ -182,85 +178,70 @@ describe('CacheClient', () => {
182
178
  cachedValue = await myObj.getCachedFunctionCall('fetchSomething', '123');
183
179
  expect(cachedValue).not.to.exist;
184
180
  });
185
-
186
181
  });
187
182
 
188
183
  describe('buildCacheKey', () => {
189
-
190
184
  class MyCacheClient extends CacheClient {
191
185
  cacheInstance = new LocalCache();
192
186
  }
193
187
 
194
188
  it('will add null or undefined to the key', async () => {
195
-
196
189
  const cacheClient = new MyCacheClient();
197
190
  const key = cacheClient['buildCacheKey']('functionName', [null, undefined, 'argument']);
198
191
  expect(key).to.equal('functionName-null-undefined-argument');
199
-
200
192
  });
201
193
 
202
194
  it('will convert boolean values', async () => {
203
-
204
195
  const cacheClient = new MyCacheClient();
205
196
  const key = cacheClient['buildCacheKey']('functionName', ['argument', true, 'argument', false]);
206
197
  expect(key).to.equal('functionName-argument-true-argument-false');
207
-
208
198
  });
209
199
 
210
200
  it('will convert number values', async () => {
211
-
212
201
  const cacheClient = new MyCacheClient();
213
202
  const key = cacheClient['buildCacheKey']('functionName', ['argument', 14, 'argument', 16]);
214
203
  expect(key).to.equal('functionName-argument-14-argument-16');
215
-
216
204
  });
217
205
 
218
206
  it('will convert plain object values', async () => {
219
207
  const cacheClient = new MyCacheClient();
220
- const expectedKey = 'functionName-argument-property1-prop1-property2-prop2-property3-nestedProp1-nestedProp1-nestedProp2-nestedProp2';
208
+ const expectedKey =
209
+ 'functionName-argument-property1-prop1-property2-prop2-property3-nestedProp1-nestedProp1-nestedProp2-nestedProp2';
221
210
 
222
211
  const keyWithSortedObjectProperties = cacheClient['buildCacheKey']('functionName', [
223
212
  'argument',
224
- { property1: 'prop1', property2: 'prop2', property3: { nestedProp1: 'nestedProp1', nestedProp2: 'nestedProp2' } },
213
+ {
214
+ property1: 'prop1',
215
+ property2: 'prop2',
216
+ property3: { nestedProp1: 'nestedProp1', nestedProp2: 'nestedProp2' },
217
+ },
225
218
  new Date(),
226
219
  ]);
227
220
  expect(keyWithSortedObjectProperties).to.equal(expectedKey);
228
- })
221
+ });
229
222
 
230
223
  it('will convert array values', async () => {
231
224
  const cacheClient = new MyCacheClient();
232
225
  const expectedKey = 'functionName-prop1-propValue1-prop2-propValue2-value1-value2';
233
226
 
234
227
  const keyWithArrayValues = cacheClient['buildCacheKey']('functionName', [
235
- [
236
- { prop1: 'propValue1', prop2: 'propValue2' },
237
- 'value1',
238
- 'value2',
239
- ],
228
+ [{ prop1: 'propValue1', prop2: 'propValue2' }, 'value1', 'value2'],
240
229
  ]);
241
230
  expect(keyWithArrayValues).to.equal(expectedKey);
242
- })
231
+ });
243
232
 
244
233
  it('will convert array values and the result should be the same key if two array own the same properties but not in the same order', async () => {
245
234
  const cacheClient = new MyCacheClient();
246
235
 
247
- const keyWithSortedArrayValues= cacheClient['buildCacheKey']('functionName', [
248
- [
249
- { prop1: 'propValue1', prop2: 'propValue2' },
250
- 'value1',
251
- 'value2',
252
- ],
236
+ const keyWithSortedArrayValues = cacheClient['buildCacheKey']('functionName', [
237
+ [{ prop1: 'propValue1', prop2: 'propValue2' }, 'value1', 'value2'],
253
238
  ]);
254
239
 
255
- const keyWithUnsortedArrayValues= cacheClient['buildCacheKey']('functionName', [
256
- [
257
- 'value1',
258
- 'value2',
259
- { prop1: 'propValue1', prop2: 'propValue2' },
260
- ],
240
+ const keyWithUnsortedArrayValues = cacheClient['buildCacheKey']('functionName', [
241
+ ['value1', 'value2', { prop1: 'propValue1', prop2: 'propValue2' }],
261
242
  ]);
262
243
  expect(keyWithSortedArrayValues).to.equal(keyWithUnsortedArrayValues);
263
- })
244
+ });
264
245
 
265
246
  it('will convert plain object values and the result should be the same key if two objects have the same properties but not in the same order', async () => {
266
247
  const cacheClient = new MyCacheClient();
@@ -277,7 +258,7 @@ describe('CacheClient', () => {
277
258
  ['value2', 'value1'],
278
259
  ]);
279
260
  expect(keyWithUnsortedObjectProperties).to.equal(keyWithSortedObjectProperties);
280
- })
261
+ });
281
262
 
282
263
  it('should throw if key is bigger than 1000', async () => {
283
264
  const cacheClient = new MyCacheClient();
@@ -288,7 +269,7 @@ describe('CacheClient', () => {
288
269
  }
289
270
 
290
271
  expect(() => cacheClient['buildCacheKey']('functionName', [bigArray])).to.throw();
291
- })
272
+ });
292
273
 
293
274
  it('should detect circular reference in an object', async () => {
294
275
  const cacheClient = new MyCacheClient();
@@ -301,18 +282,18 @@ describe('CacheClient', () => {
301
282
  obj2.property1 = obj;
302
283
 
303
284
  expect(() => cacheClient['buildCacheKey']('functionName', [obj2])).to.throw();
304
- })
285
+ });
305
286
  });
306
287
 
307
288
  describe('Redlock maintenance reminder', () => {
308
-
309
289
  it('is still on Redlock v4, or was carefully migrated to v5', () => {
310
290
  // eslint-disable-next-line @typescript-eslint/no-require-imports
311
291
  const redlockVersion = require('../../package.json').dependencies.redlock;
312
292
  if (redlockVersion !== '4.x') {
313
- throw new Error('Migrating Redlock to v5? This breaking test is a reminder to:\n 1. Migrate v4 handling of `clientError` events into v5 `error` events\n 2. Review error handling: Redlock v5 throws at many places, while Redlock v4 only threw in its constructor\n 3. Review other breaking changes provided by the upgrade guide, if Redlock maintainers provide one when shipping v5');
293
+ throw new Error(
294
+ 'Migrating Redlock to v5? This breaking test is a reminder to:\n 1. Migrate v4 handling of `clientError` events into v5 `error` events\n 2. Review error handling: Redlock v5 throws at many places, while Redlock v4 only threw in its constructor\n 3. Review other breaking changes provided by the upgrade guide, if Redlock maintainers provide one when shipping v5',
295
+ );
314
296
  }
315
297
  });
316
-
317
298
  });
318
299
  });
@@ -7,14 +7,13 @@ import { WriteThroughCache } from '../src/lib/WriteThroughCache';
7
7
  import { CacheInstance, FetchingFunction } from '../src/lib/CacheInstance';
8
8
 
9
9
  async function sleep(ms: number): Promise<void> {
10
- return new Promise(resolve => setTimeout(resolve, ms));
10
+ return new Promise((resolve) => setTimeout(resolve, ms));
11
11
  }
12
12
 
13
13
  // set env var TEST_REDIS_URL (e.g. redis://localhost:6379) to enable running
14
14
  // the tests with Redis
15
15
 
16
16
  describe('CacheInstance', () => {
17
-
18
17
  runTests('local', new LocalCache());
19
18
 
20
19
  if (process.env.TEST_REDIS_URL) {
@@ -24,13 +23,11 @@ describe('CacheInstance', () => {
24
23
  const writeThroughCache = new WriteThroughCache(process.env.TEST_REDIS_URL);
25
24
  runTests('writeThrough', writeThroughCache);
26
25
  }
27
-
28
26
  });
29
27
 
30
28
  function runTests(name: string, cache: CacheInstance): void {
31
-
32
29
  const lockSupported = cache.isLockingSupported();
33
- const ifLockIt = (cache && cache.isLockingSupported()) ? it : it.skip;
30
+ const ifLockIt = cache && cache.isLockingSupported() ? it : it.skip;
34
31
  let lockSpy: sinon.SinonSpy;
35
32
  let unlockSpy: sinon.SinonSpy;
36
33
 
@@ -57,9 +54,7 @@ function runTests(name: string, cache: CacheInstance): void {
57
54
  }
58
55
  });
59
56
 
60
-
61
57
  describe(`getOrFetchValue - ${name}`, () => {
62
-
63
58
  beforeEach(() => cache.clear());
64
59
 
65
60
  it('does not fetch if value in cache', async () => {
@@ -94,11 +89,7 @@ function runTests(name: string, cache: CacheInstance): void {
94
89
 
95
90
  await cache.setValue('key2', 'value');
96
91
  const fetchFunction = object.fetch.bind(object, 'newvalue');
97
- const value = await cache.getOrFetchValue(
98
- 'key',
99
- 10,
100
- fetchFunction,
101
- );
92
+ const value = await cache.getOrFetchValue('key', 10, fetchFunction);
102
93
  expect(value).to.eql('newvalue');
103
94
  expect(numCalled).to.eql(1);
104
95
  if (lockSupported) {
@@ -194,13 +185,8 @@ function runTests(name: string, cache: CacheInstance): void {
194
185
  const fetchFunction = object.fetchThatThrowsAfterThree.bind(object, 'newvalue');
195
186
 
196
187
  let didThrow = false;
197
- const getFromCache = async () => cache.getOrFetchValue(
198
- 'key',
199
- 10,
200
- fetchFunction,
201
- undefined,
202
- (err) => err.name !== 'NonCacheableError',
203
- );
188
+ const getFromCache = async () =>
189
+ cache.getOrFetchValue('key', 10, fetchFunction, undefined, (err) => err.name !== 'NonCacheableError');
204
190
  try {
205
191
  await getFromCache();
206
192
  } catch (err) {
@@ -258,11 +244,7 @@ function runTests(name: string, cache: CacheInstance): void {
258
244
  await cache.setValue('key2', 'value');
259
245
 
260
246
  const fetchFunction = object.fetch.bind(object, 'newvalue');
261
- const callGetOrFetch = () => cache.getOrFetchValue(
262
- 'key',
263
- 10,
264
- fetchFunction,
265
- );
247
+ const callGetOrFetch = () => cache.getOrFetchValue('key', 10, fetchFunction);
266
248
 
267
249
  const calls: Promise<any>[] = [];
268
250
  for (let i = 0; i < 100; i++) {
@@ -293,18 +275,14 @@ function runTests(name: string, cache: CacheInstance): void {
293
275
 
294
276
  const callGetOrFetch = (key, fn) => {
295
277
  const fetchFunction = fn.bind(object, 'newvalue');
296
- return cache.getOrFetchValue(
297
- key,
298
- 10,
299
- fetchFunction,
300
- );
278
+ return cache.getOrFetchValue(key, 10, fetchFunction);
301
279
  };
302
280
 
303
281
  const calls: Promise<any>[] = [];
304
282
 
305
283
  for (let i = 0; i < 100; i++) {
306
- const fn = (i % 2) ? object.fetch1 : object.fetch2;
307
- const key = (i % 2) ? 'key1' : 'key2';
284
+ const fn = i % 2 ? object.fetch1 : object.fetch2;
285
+ const key = i % 2 ? 'key1' : 'key2';
308
286
  calls.push(callGetOrFetch(key, fn as FetchingFunction));
309
287
  }
310
288
 
@@ -334,11 +312,7 @@ function runTests(name: string, cache: CacheInstance): void {
334
312
  },
335
313
  };
336
314
 
337
- const callGetOrFetch = () => cache.getOrFetchValue(
338
- 'key',
339
- 10,
340
- object.fetch,
341
- );
315
+ const callGetOrFetch = () => cache.getOrFetchValue('key', 10, object.fetch);
342
316
 
343
317
  const calls: Promise<any>[] = [];
344
318
  for (let i = 0; i < 10; i++) {
@@ -448,7 +422,7 @@ function runTests(name: string, cache: CacheInstance): void {
448
422
  };
449
423
 
450
424
  const fetchFunction = object.fetch.bind(object, 'newvalue');
451
- const value = await cache.getOrFetchValue(key, 10, fetchFunction, 1); // enable locking
425
+ const value = await cache.getOrFetchValue(key, 10, fetchFunction, 1); // enable locking
452
426
 
453
427
  expect(value).to.eql('newvalue');
454
428
  expect(numCalled).to.eql(1);
@@ -479,10 +453,8 @@ function runTests(name: string, cache: CacheInstance): void {
479
453
 
480
454
  expect(value).to.eql('abcd');
481
455
  expect(numCalled).to.eql(0);
482
- sinon.assert.calledTwice(lockSpy); // includes our own call above
456
+ sinon.assert.calledTwice(lockSpy); // includes our own call above
483
457
  sinon.assert.calledTwice(unlockSpy);
484
458
  });
485
-
486
459
  });
487
-
488
460
  }