mirror of
https://github.com/expo/entity.git
synced 2026-11-13 20:28:06 -10:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b61341057b | ||
|
|
bc378b6c79 |
No files matched your search
@@ -1,4 +1,4 @@
|
||||
import { CacheLoadResult, CacheStatus } from '@expo/entity';
|
||||
import { CacheLoadResult, CacheStatus, IEntityGenericCacher } from '@expo/entity';
|
||||
import LRUCache from 'lru-cache';
|
||||
|
||||
// Sentinel value we store in local memory to negatively cache a database miss.
|
||||
@@ -77,8 +77,8 @@ type LRUCacheOptionsV7<K, V> = {
|
||||
updateRecencyOnHas?: boolean;
|
||||
};
|
||||
|
||||
export default class GenericLocalMemoryCacher<TFields> {
|
||||
constructor(private readonly lruCache: LocalMemoryCache<TFields>) {}
|
||||
export default class GenericLocalMemoryCacher<TFields> implements IEntityGenericCacher<TFields> {
|
||||
constructor(private readonly localMemoryCache: LocalMemoryCache<TFields>) {}
|
||||
|
||||
static createLRUCache<TFields>(
|
||||
options: { maxSize?: number; ttlSeconds?: number } = {}
|
||||
@@ -95,7 +95,7 @@ export default class GenericLocalMemoryCacher<TFields> {
|
||||
return new LRUCache<string, LocalMemoryCacheValue<TFields>>(lruCacheOptions as any);
|
||||
}
|
||||
|
||||
static createNoOpLRUCache<TFields>(): LocalMemoryCache<TFields> {
|
||||
static createNoOpCache<TFields>(): LocalMemoryCache<TFields> {
|
||||
return new LRUCache<string, LocalMemoryCacheValue<TFields>>({
|
||||
max: 0,
|
||||
maxAge: -1,
|
||||
@@ -107,7 +107,7 @@ export default class GenericLocalMemoryCacher<TFields> {
|
||||
): Promise<ReadonlyMap<string, CacheLoadResult<TFields>>> {
|
||||
const cacheResults = new Map<string, CacheLoadResult<TFields>>();
|
||||
for (const key of keys) {
|
||||
const cacheResult = this.lruCache.get(key);
|
||||
const cacheResult = this.localMemoryCache.get(key);
|
||||
if (cacheResult === DOES_NOT_EXIST_LOCAL_MEMORY_CACHE) {
|
||||
cacheResults.set(key, {
|
||||
status: CacheStatus.NEGATIVE,
|
||||
@@ -128,19 +128,19 @@ export default class GenericLocalMemoryCacher<TFields> {
|
||||
|
||||
public async cacheManyAsync(objectMap: ReadonlyMap<string, Readonly<TFields>>): Promise<void> {
|
||||
for (const [key, item] of objectMap) {
|
||||
this.lruCache.set(key, item);
|
||||
this.localMemoryCache.set(key, item);
|
||||
}
|
||||
}
|
||||
|
||||
public async cacheDBMissesAsync(keys: string[]): Promise<void> {
|
||||
public async cacheDBMissesAsync(keys: readonly string[]): Promise<void> {
|
||||
for (const key of keys) {
|
||||
this.lruCache.set(key, DOES_NOT_EXIST_LOCAL_MEMORY_CACHE);
|
||||
this.localMemoryCache.set(key, DOES_NOT_EXIST_LOCAL_MEMORY_CACHE);
|
||||
}
|
||||
}
|
||||
|
||||
public async invalidateManyAsync(keys: string[]): Promise<void> {
|
||||
public async invalidateManyAsync(keys: readonly string[]): Promise<void> {
|
||||
for (const key of keys) {
|
||||
this.lruCache.del(key);
|
||||
this.localMemoryCache.del(key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,10 @@ export default class LocalMemoryCacheAdapter<TFields> extends EntityCacheAdapter
|
||||
|
||||
constructor(
|
||||
entityConfiguration: EntityConfiguration<TFields>,
|
||||
lruCache: LocalMemoryCache<TFields>
|
||||
localMemoryCache: LocalMemoryCache<TFields>
|
||||
) {
|
||||
super(entityConfiguration);
|
||||
this.genericLocalMemoryCacher = new GenericLocalMemoryCacher(lruCache);
|
||||
this.genericLocalMemoryCacher = new GenericLocalMemoryCacher(localMemoryCache);
|
||||
}
|
||||
|
||||
public async loadManyAsync<N extends keyof TFields>(
|
||||
@@ -29,7 +29,7 @@ export default class LocalMemoryCacheAdapter<TFields> extends EntityCacheAdapter
|
||||
const fieldValue = localMemoryCacheKeyToFieldValueMapping.get(cacheKey);
|
||||
invariant(
|
||||
fieldValue !== undefined,
|
||||
'Unspecified cache key %s returned from generic Local Memory cacher',
|
||||
'Unspecified cache key %s returned from generic local memory cacher',
|
||||
cacheKey
|
||||
);
|
||||
return fieldValue;
|
||||
|
||||
@@ -8,13 +8,13 @@ import {
|
||||
import GenericLocalMemoryCacher, { LocalMemoryCache } from './GenericLocalMemoryCacher';
|
||||
import LocalMemoryCacheAdapter from './LocalMemoryCacheAdapter';
|
||||
|
||||
export class LocalMemoryCacheAdapterProvider implements IEntityCacheAdapterProvider {
|
||||
export default class LocalMemoryCacheAdapterProvider implements IEntityCacheAdapterProvider {
|
||||
// local memory cache adapters should be shared/reused across requests
|
||||
static localMemoryCacheAdapterMap = new Map<string, LocalMemoryCacheAdapter<any>>();
|
||||
|
||||
static getNoOpProvider(): IEntityCacheAdapterProvider {
|
||||
return new LocalMemoryCacheAdapterProvider(<TFields>() =>
|
||||
GenericLocalMemoryCacher.createNoOpLRUCache<TFields>()
|
||||
GenericLocalMemoryCacher.createNoOpCache<TFields>()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,9 @@ export class LocalMemoryCacheAdapterProvider implements IEntityCacheAdapterProvi
|
||||
);
|
||||
}
|
||||
|
||||
private constructor(private readonly lruCacheCreator: <TFields>() => LocalMemoryCache<TFields>) {}
|
||||
private constructor(
|
||||
private readonly localMemoryCacheCreator: <TFields>() => LocalMemoryCache<TFields>
|
||||
) {}
|
||||
|
||||
public getCacheAdapter<TFields>(
|
||||
entityConfiguration: EntityConfiguration<TFields>
|
||||
@@ -35,8 +37,8 @@ export class LocalMemoryCacheAdapterProvider implements IEntityCacheAdapterProvi
|
||||
LocalMemoryCacheAdapterProvider.localMemoryCacheAdapterMap,
|
||||
entityConfiguration.tableName,
|
||||
() => {
|
||||
const lruCache = this.lruCacheCreator<TFields>();
|
||||
return new LocalMemoryCacheAdapter(entityConfiguration, lruCache);
|
||||
const localMemoryCache = this.localMemoryCacheCreator<TFields>();
|
||||
return new LocalMemoryCacheAdapter(entityConfiguration, localMemoryCache);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
+8
-8
@@ -64,16 +64,16 @@ describe(LocalMemoryCacheAdapter, () => {
|
||||
|
||||
describe('cacheManyAsync', () => {
|
||||
it('correctly caches all objects', async () => {
|
||||
const lruCache = GenericLocalMemoryCacher.createLRUCache<BlahFields>({
|
||||
const localMemoryCache = GenericLocalMemoryCacher.createLRUCache<BlahFields>({
|
||||
maxSize: Number.MAX_SAFE_INTEGER,
|
||||
ttlSeconds: Number.MAX_SAFE_INTEGER,
|
||||
});
|
||||
|
||||
const cacheAdapter = new LocalMemoryCacheAdapter(entityConfiguration, lruCache);
|
||||
const cacheAdapter = new LocalMemoryCacheAdapter(entityConfiguration, localMemoryCache);
|
||||
await cacheAdapter.cacheManyAsync('id', new Map([['test-id-1', { id: 'test-id-1' }]]));
|
||||
|
||||
const cacheKey = cacheAdapter['makeCacheKey']('id', 'test-id-1');
|
||||
expect(lruCache.get(cacheKey)).toMatchObject({
|
||||
expect(localMemoryCache.get(cacheKey)).toMatchObject({
|
||||
id: 'test-id-1',
|
||||
});
|
||||
});
|
||||
@@ -81,27 +81,27 @@ describe(LocalMemoryCacheAdapter, () => {
|
||||
|
||||
describe('cacheDBMissesAsync', () => {
|
||||
it('correctly caches misses', async () => {
|
||||
const lruCache = GenericLocalMemoryCacher.createLRUCache<BlahFields>({
|
||||
const localMemoryCache = GenericLocalMemoryCacher.createLRUCache<BlahFields>({
|
||||
maxSize: Number.MAX_SAFE_INTEGER,
|
||||
ttlSeconds: Number.MAX_SAFE_INTEGER,
|
||||
});
|
||||
|
||||
const cacheAdapter = new LocalMemoryCacheAdapter(entityConfiguration, lruCache);
|
||||
const cacheAdapter = new LocalMemoryCacheAdapter(entityConfiguration, localMemoryCache);
|
||||
await cacheAdapter.cacheDBMissesAsync('id', ['test-id-1']);
|
||||
|
||||
const cacheKey = cacheAdapter['makeCacheKey']('id', 'test-id-1');
|
||||
expect(lruCache.get(cacheKey)).toEqual(DOES_NOT_EXIST_LOCAL_MEMORY_CACHE);
|
||||
expect(localMemoryCache.get(cacheKey)).toEqual(DOES_NOT_EXIST_LOCAL_MEMORY_CACHE);
|
||||
});
|
||||
});
|
||||
|
||||
describe('invalidateManyAsync', () => {
|
||||
it('invalidates correctly', async () => {
|
||||
const lruCache = GenericLocalMemoryCacher.createLRUCache<BlahFields>({
|
||||
const localMemoryCache = GenericLocalMemoryCacher.createLRUCache<BlahFields>({
|
||||
maxSize: Number.MAX_SAFE_INTEGER,
|
||||
ttlSeconds: Number.MAX_SAFE_INTEGER,
|
||||
});
|
||||
|
||||
const cacheAdapter = new LocalMemoryCacheAdapter(entityConfiguration, lruCache);
|
||||
const cacheAdapter = new LocalMemoryCacheAdapter(entityConfiguration, localMemoryCache);
|
||||
await cacheAdapter.cacheManyAsync('id', new Map([['test-id-1', { id: 'test-id-1' }]]));
|
||||
await cacheAdapter.cacheDBMissesAsync('id', ['test-id-2']);
|
||||
await cacheAdapter.invalidateManyAsync('id', ['test-id-1', 'test-id-2']);
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
/* eslint-disable tsdoc/syntax */
|
||||
/**
|
||||
* @packageDocumentation
|
||||
* @module @expo/entity-cache-adapter-local-memory
|
||||
*/
|
||||
|
||||
export { default as LocalMemoryCacheAdapter } from './LocalMemoryCacheAdapter';
|
||||
export { default as LocalMemoryCacheAdapterProvider } from './LocalMemoryCacheAdapterProvider';
|
||||
export { default as GenericLocalMemoryCacher } from './GenericLocalMemoryCacher';
|
||||
export * from './GenericLocalMemoryCacher';
|
||||
@@ -97,7 +97,7 @@ export default class GenericRedisCacher<TFields> implements IEntityGenericCacher
|
||||
await wrapNativeRedisCallAsync(() => redisTransaction.exec());
|
||||
}
|
||||
|
||||
public async cacheDBMissesAsync(keys: string[]): Promise<void> {
|
||||
public async cacheDBMissesAsync(keys: readonly string[]): Promise<void> {
|
||||
if (keys.length === 0) {
|
||||
return;
|
||||
}
|
||||
@@ -114,7 +114,7 @@ export default class GenericRedisCacher<TFields> implements IEntityGenericCacher
|
||||
await wrapNativeRedisCallAsync(() => redisTransaction.exec());
|
||||
}
|
||||
|
||||
public async invalidateManyAsync(keys: string[]): Promise<void> {
|
||||
public async invalidateManyAsync(keys: readonly string[]): Promise<void> {
|
||||
if (keys.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ export default interface IEntityGenericCacher<TFields> {
|
||||
|
||||
cacheManyAsync(objectMap: ReadonlyMap<string, Readonly<TFields>>): Promise<void>;
|
||||
|
||||
cacheDBMissesAsync(keys: string[]): Promise<void>;
|
||||
cacheDBMissesAsync(keys: readonly string[]): Promise<void>;
|
||||
|
||||
invalidateManyAsync(keys: string[]): Promise<void>;
|
||||
invalidateManyAsync(keys: readonly string[]): Promise<void>;
|
||||
}
|
||||
Reference in new issue
Block a user