apollo-server-caching
Advanced tools
Comparing version 0.2.1 to 0.2.2
import { KeyValueCache } from './KeyValueCache'; | ||
export declare class InMemoryLRUCache implements KeyValueCache { | ||
export declare class InMemoryLRUCache<V = string> implements KeyValueCache<V> { | ||
private store; | ||
@@ -7,6 +7,9 @@ constructor({ maxSize }?: { | ||
}); | ||
get(key: string): Promise<string | undefined>; | ||
set(key: string, value: string): Promise<void>; | ||
get(key: string): Promise<V | undefined>; | ||
set(key: string, value: V, options?: { | ||
ttl?: number; | ||
}): Promise<void>; | ||
delete(key: string): Promise<void>; | ||
flush(): Promise<void>; | ||
} | ||
//# sourceMappingURL=InMemoryLRUCache.d.ts.map |
@@ -19,3 +19,11 @@ "use strict"; | ||
max: maxSize, | ||
length: item => item.length, | ||
length(item) { | ||
if (Array.isArray(item) || typeof item === 'string') { | ||
return item.length; | ||
} | ||
if (typeof item === 'object') { | ||
return JSON.stringify(item).length; | ||
} | ||
return 1; | ||
}, | ||
}); | ||
@@ -28,5 +36,6 @@ } | ||
} | ||
set(key, value) { | ||
set(key, value, options) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
this.store.set(key, value); | ||
const maxAge = options && options.ttl && options.ttl * 1000; | ||
this.store.set(key, value, maxAge); | ||
}); | ||
@@ -39,4 +48,9 @@ } | ||
} | ||
flush() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
this.store.reset(); | ||
}); | ||
} | ||
} | ||
exports.InMemoryLRUCache = InMemoryLRUCache; | ||
//# sourceMappingURL=InMemoryLRUCache.js.map |
@@ -1,4 +0,4 @@ | ||
export interface KeyValueCache { | ||
get(key: string): Promise<string | undefined>; | ||
set(key: string, value: string, options?: { | ||
export interface KeyValueCache<V = string> { | ||
get(key: string): Promise<V | undefined>; | ||
set(key: string, value: V, options?: { | ||
ttl?: number; | ||
@@ -5,0 +5,0 @@ }): Promise<void>; |
{ | ||
"name": "apollo-server-caching", | ||
"version": "0.2.1", | ||
"version": "0.2.2", | ||
"author": "opensource@apollographql.com", | ||
@@ -22,3 +22,3 @@ "license": "MIT", | ||
}, | ||
"gitHead": "1f3801c94967941f539e4bf925c92134b56478e7" | ||
"gitHead": "d48d0972c5730ea63969daa892f58a34aa1db543" | ||
} |
@@ -19,4 +19,6 @@ # apollo-server-caching | ||
## Running test suite | ||
## Testing cache implementations | ||
### Test helpers | ||
You can export and run a jest test suite from `apollo-server-caching` to test your implementation: | ||
@@ -32,2 +34,13 @@ | ||
The default `testKeyValueCache` helper will run all key-value store tests on the specified store, including basic `get` and `set` functionality, along with time-based expunging rules. | ||
Some key-value cache implementations may not be able to support the full suite of tests (for example, some tests might not be able to expire based on time). For those cases, there are more granular implementations which can be used: | ||
* `testKeyValueCache_Basic` | ||
* `testKeyValueCache_Expiration` | ||
For more details, consult the [source for `apollo-server-caching`](./src/__tests__/testsuite.ts). | ||
### Running tests | ||
Run tests with `jest --verbose` |
import { advanceTimeBy, mockDate, unmockDate } from '__mocks__/date'; | ||
export function testKeyValueCache(keyValueCache: any) { | ||
describe('KeyValueCache Test Suite', () => { | ||
beforeAll(() => { | ||
mockDate(); | ||
jest.useFakeTimers(); | ||
}); | ||
export function testKeyValueCache_Basics(keyValueCache: any) { | ||
describe('basic cache functionality', () => { | ||
beforeEach(() => { | ||
@@ -14,7 +9,2 @@ keyValueCache.flush(); | ||
afterAll(() => { | ||
unmockDate(); | ||
keyValueCache.close(); | ||
}); | ||
it('can do a basic get and set', async () => { | ||
@@ -32,3 +22,21 @@ await keyValueCache.set('hello', 'world'); | ||
}); | ||
}); | ||
} | ||
export function testKeyValueCache_Expiration(keyValueCache: any) { | ||
describe('time-based cache expunging', () => { | ||
beforeAll(() => { | ||
mockDate(); | ||
jest.useFakeTimers(); | ||
}); | ||
beforeEach(() => { | ||
keyValueCache.flush(); | ||
}); | ||
afterAll(() => { | ||
unmockDate(); | ||
keyValueCache.close(); | ||
}); | ||
it('is able to expire keys based on ttl', async () => { | ||
@@ -50,1 +58,8 @@ await keyValueCache.set('short', 's', { ttl: 1 }); | ||
} | ||
export function testKeyValueCache(keyValueCache: any) { | ||
describe('KeyValueCache Test Suite', () => { | ||
testKeyValueCache_Basics(keyValueCache); | ||
testKeyValueCache_Expiration(keyValueCache); | ||
}); | ||
} |
import LRU from 'lru-cache'; | ||
import { KeyValueCache } from './KeyValueCache'; | ||
export class InMemoryLRUCache implements KeyValueCache { | ||
private store: LRU.Cache<string, string>; | ||
export class InMemoryLRUCache<V = string> implements KeyValueCache<V> { | ||
private store: LRU.Cache<string, V>; | ||
@@ -11,3 +11,21 @@ // FIXME: Define reasonable default max size of the cache | ||
max: maxSize, | ||
length: item => item.length, | ||
length(item) { | ||
if (Array.isArray(item) || typeof item === 'string') { | ||
return item.length; | ||
} | ||
// If it's an object, we'll use the length to get an approximate, | ||
// relative size of what it would take to store it. It's certainly not | ||
// 100% accurate, but it's a very, very fast implementation and it | ||
// doesn't require bringing in other dependencies or logic which we need | ||
// to maintain. In the future, we might consider something like: | ||
// npm.im/object-sizeof, but this should be sufficient for now. | ||
if (typeof item === 'object') { | ||
return JSON.stringify(item).length; | ||
} | ||
// Go with the lru-cache default "naive" size, in lieu anything better: | ||
// https://github.com/isaacs/node-lru-cache/blob/a71be6cd/index.js#L17 | ||
return 1; | ||
}, | ||
}); | ||
@@ -19,4 +37,5 @@ } | ||
} | ||
async set(key: string, value: string) { | ||
this.store.set(key, value); | ||
async set(key: string, value: V, options?: { ttl?: number }) { | ||
const maxAge = options && options.ttl && options.ttl * 1000; | ||
this.store.set(key, value, maxAge); | ||
} | ||
@@ -26,2 +45,5 @@ async delete(key: string) { | ||
} | ||
async flush(): Promise<void> { | ||
this.store.reset(); | ||
} | ||
} |
@@ -1,5 +0,5 @@ | ||
export interface KeyValueCache { | ||
get(key: string): Promise<string | undefined>; | ||
set(key: string, value: string, options?: { ttl?: number }): Promise<void>; | ||
export interface KeyValueCache<V = string> { | ||
get(key: string): Promise<V | undefined>; | ||
set(key: string, value: V, options?: { ttl?: number }): Promise<void>; | ||
delete(key: string): Promise<boolean | void>; | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
13915
21
199
45