diff --git a/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.test.ts b/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.test.ts index a3fc607404..9675a285e0 100644 --- a/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.test.ts +++ b/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.test.ts @@ -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( diff --git a/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.ts b/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.ts index 2bd0f0b038..8442983637 100644 --- a/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.ts +++ b/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.ts @@ -77,22 +77,26 @@ export class TodoScmReader implements TodoReader { } async readTodos({ url }: ReadTodosOptions): Promise { + 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); } }