diff --git a/packages/aelis-source-tfl/src/tfl-api.ts b/packages/aelis-source-tfl/src/tfl-api.ts index e2f7e98..7b726aa 100644 --- a/packages/aelis-source-tfl/src/tfl-api.ts +++ b/packages/aelis-source-tfl/src/tfl-api.ts @@ -69,7 +69,7 @@ export class TflApi { } async fetchLineStatuses(lines?: TflLineId[]): Promise { - const lineIds = lines ?? ALL_LINE_IDS + const lineIds = lines?.length ? lines : ALL_LINE_IDS const data = await this.fetch(`/Line/${lineIds.join(",")}/Status`) const parsed = lineResponseArray(data) @@ -101,8 +101,8 @@ export class TflApi { return this.stationsCache } - // Fetch stations for all lines in parallel - const responses = await Promise.all( + // Fetch stations for all lines in parallel, tolerating individual failures + const results = await Promise.allSettled( ALL_LINE_IDS.map(async (id) => { const data = await this.fetch(`/Line/${id}/StopPoints`) const parsed = lineStopPointsArray(data) @@ -116,7 +116,12 @@ export class TflApi { // Merge stations, combining lines for shared stations const stationMap = new Map() - for (const { lineId: currentLineId, stops } of responses) { + for (const result of results) { + if (result.status === "rejected") { + continue + } + + const { lineId: currentLineId, stops } = result.value for (const stop of stops) { const existing = stationMap.get(stop.naptanId) if (existing) { @@ -135,8 +140,15 @@ export class TflApi { } } - this.stationsCache = Array.from(stationMap.values()) - return this.stationsCache + // Only cache if all requests succeeded — partial results shouldn't persist + const allSucceeded = results.every((r) => r.status === "fulfilled") + const stations = Array.from(stationMap.values()) + + if (allSucceeded) { + this.stationsCache = stations + } + + return stations } } diff --git a/packages/aelis-source-tfl/src/tfl-source.ts b/packages/aelis-source-tfl/src/tfl-source.ts index a72667b..4d4637f 100644 --- a/packages/aelis-source-tfl/src/tfl-source.ts +++ b/packages/aelis-source-tfl/src/tfl-source.ts @@ -84,7 +84,7 @@ export class TflSource implements FeedSource { throw new Error("Either client or apiKey must be provided") } this.client = options.client ?? new TflApi(options.apiKey!) - this.lines = options.lines ?? [...TflSource.DEFAULT_LINES_OF_INTEREST] + this.lines = options.lines?.length ? options.lines : [...TflSource.DEFAULT_LINES_OF_INTEREST] } async listActions(): Promise> {