Cancel cache read if it takes too long

Signed-off-by: Joe Porpeglia <josephp@spotify.com>
This commit is contained in:
Joe Porpeglia
2022-01-07 17:47:59 -05:00
committed by Joe Porpeglia
parent f5598677bf
commit 413c9fab08
2 changed files with 29 additions and 4 deletions
@@ -130,4 +130,19 @@ describe('CachedEntityLoader', () => {
ttl: 5000,
});
});
it('calls the catalog if the cache read takes too long', async () => {
identity.authenticate.mockResolvedValue(identityResponse);
cache.get.mockImplementation(
() =>
new Promise(resolve => {
setTimeout(() => resolve(undefined), 10000);
}),
);
catalog.getEntityByName.mockResolvedValue(entity);
const result = await loader.load(entityName, token);
expect(result).toEqual(entity);
});
});
@@ -30,9 +30,10 @@ export type CachedEntityLoaderOptions = {
};
export class CachedEntityLoader {
private catalog: CatalogClient;
private cache: CacheClient;
private identity: IdentityClient;
private readonly catalog: CatalogClient;
private readonly cache: CacheClient;
private readonly identity: IdentityClient;
private readonly readTimeout = 1000;
constructor({ catalog, cache, identity }: CachedEntityLoaderOptions) {
this.catalog = catalog;
@@ -45,7 +46,7 @@ export class CachedEntityLoader {
token: string | undefined,
): Promise<Entity | undefined> {
const cacheKey = await this.getCacheKey(entityName, token);
let result = (await this.cache.get(cacheKey)) as Entity | undefined;
let result = await this.getFromCache(cacheKey);
if (result) {
return result;
@@ -68,6 +69,15 @@ export class CachedEntityLoader {
return result;
}
private async getFromCache(key: string): Promise<Entity | undefined> {
// Promise.race ensures we don't hang the client for long if the cache is
// temporarily unreachable.
return (await Promise.race([
this.cache.get(key),
new Promise(cancelAfter => setTimeout(cancelAfter, this.readTimeout)),
])) as Entity | undefined;
}
private async getCacheKey(
entityName: EntityName,
token: string | undefined,