todo-backend: fix TodoScmReader caching logic

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2021-08-17 13:55:13 +02:00
parent c8fd2fc190
commit 8f2c880b80
2 changed files with 22 additions and 12 deletions
@@ -74,7 +74,13 @@ describe('TodoScmReader', () => {
],
};
await expect(todoReader.readTodos({ url })).resolves.toEqual(expected);
// These two reads should only result in a single call to readTree
await expect(
Promise.all([
todoReader.readTodos({ url }),
todoReader.readTodos({ url }),
]),
).resolves.toEqual([expected, expected]);
expect(reader.readTree).toHaveBeenCalledTimes(1);
expect(reader.readTree).toHaveBeenCalledWith(
@@ -77,22 +77,26 @@ export class TodoScmReader implements TodoReader {
}
async readTodos({ url }: ReadTodosOptions): Promise<ReadTodosResult> {
const inFlightRead = this.inFlightReads.get(url);
if (inFlightRead) {
return inFlightRead.then(read => read.result);
}
const cacheItem = this.cache.get(url);
try {
const inFlightRead = this.inFlightReads.get(url);
if (inFlightRead) {
return (await inFlightRead).result;
const newRead = this.doReadTodos({ url }, cacheItem?.etag).catch(error => {
if (cacheItem && error.name === 'NotModifiedError') {
return cacheItem;
}
const newRead = this.doReadTodos({ url }, cacheItem?.etag);
this.inFlightReads.set(url, newRead);
throw error;
});
this.inFlightReads.set(url, newRead);
try {
const newCacheItem = await newRead;
this.cache.set(url, newCacheItem);
return newCacheItem.result;
} catch (error) {
if (cacheItem && error.name === 'NotModifiedError') {
return cacheItem.result;
}
throw error;
} finally {
this.inFlightReads.delete(url);
}
}