From e220ccc39292a2ac1c42b93f57e9729ba4bae4ae Mon Sep 17 00:00:00 2001 From: kenneth Date: Sat, 28 Feb 2026 15:53:36 +0000 Subject: [PATCH] fix: deduplicate concurrent fetchEvents calls Co-authored-by: Ona --- .../aris-source-caldav/src/caldav-source.ts | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/packages/aris-source-caldav/src/caldav-source.ts b/packages/aris-source-caldav/src/caldav-source.ts index 511da52..23e9dfc 100644 --- a/packages/aris-source-caldav/src/caldav-source.ts +++ b/packages/aris-source-caldav/src/caldav-source.ts @@ -75,6 +75,7 @@ export class CalDavSource implements FeedSource { private readonly injectedClient: CalDavDAVClient | null private clientPromise: Promise | null = null private cachedEvents: { time: Date; events: CalDavEventData[] } | null = null + private pendingFetch: { time: Date; promise: Promise } | null = null constructor(options: CalDavSourceOptions) { this.options = options @@ -127,11 +128,27 @@ export class CalDavSource implements FeedSource { return events.map((event) => createFeedItem(event, now)) } - private async fetchEvents(context: Context): Promise { + private fetchEvents(context: Context): Promise { if (this.cachedEvents && this.cachedEvents.time === context.time) { - return this.cachedEvents.events + return Promise.resolve(this.cachedEvents.events) } + // Deduplicate concurrent fetches for the same context.time reference + if (this.pendingFetch && this.pendingFetch.time === context.time) { + return this.pendingFetch.promise + } + + const promise = this.doFetchEvents(context).finally(() => { + if (this.pendingFetch?.promise === promise) { + this.pendingFetch = null + } + }) + + this.pendingFetch = { time: context.time, promise } + return promise + } + + private async doFetchEvents(context: Context): Promise { const client = await this.connectClient() const calendars = await client.fetchCalendars()