mirror of
https://github.com/kennethnym/aris.git
synced 2026-03-31 23:21:18 +01:00
fix: handle empty lines array in TFL source
Empty lines array caused fetchLineStatuses to build /Line//Status URL, resulting in a 404 from the TFL API. Now defaults to all lines when the array is empty. Also switches fetchStations to Promise.allSettled so individual line failures don't break the entire station fetch. Co-authored-by: Ona <no-reply@ona.com>
This commit is contained in:
@@ -69,7 +69,7 @@ export class TflApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fetchLineStatuses(lines?: TflLineId[]): Promise<TflLineStatus[]> {
|
async fetchLineStatuses(lines?: TflLineId[]): Promise<TflLineStatus[]> {
|
||||||
const lineIds = lines ?? ALL_LINE_IDS
|
const lineIds = lines?.length ? lines : ALL_LINE_IDS
|
||||||
const data = await this.fetch<unknown>(`/Line/${lineIds.join(",")}/Status`)
|
const data = await this.fetch<unknown>(`/Line/${lineIds.join(",")}/Status`)
|
||||||
|
|
||||||
const parsed = lineResponseArray(data)
|
const parsed = lineResponseArray(data)
|
||||||
@@ -101,8 +101,8 @@ export class TflApi {
|
|||||||
return this.stationsCache
|
return this.stationsCache
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch stations for all lines in parallel
|
// Fetch stations for all lines in parallel, tolerating individual failures
|
||||||
const responses = await Promise.all(
|
const results = await Promise.allSettled(
|
||||||
ALL_LINE_IDS.map(async (id) => {
|
ALL_LINE_IDS.map(async (id) => {
|
||||||
const data = await this.fetch<unknown>(`/Line/${id}/StopPoints`)
|
const data = await this.fetch<unknown>(`/Line/${id}/StopPoints`)
|
||||||
const parsed = lineStopPointsArray(data)
|
const parsed = lineStopPointsArray(data)
|
||||||
@@ -116,7 +116,12 @@ export class TflApi {
|
|||||||
// Merge stations, combining lines for shared stations
|
// Merge stations, combining lines for shared stations
|
||||||
const stationMap = new Map<string, StationLocation>()
|
const stationMap = new Map<string, StationLocation>()
|
||||||
|
|
||||||
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) {
|
for (const stop of stops) {
|
||||||
const existing = stationMap.get(stop.naptanId)
|
const existing = stationMap.get(stop.naptanId)
|
||||||
if (existing) {
|
if (existing) {
|
||||||
@@ -135,8 +140,15 @@ export class TflApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.stationsCache = Array.from(stationMap.values())
|
// Only cache if all requests succeeded — partial results shouldn't persist
|
||||||
return this.stationsCache
|
const allSucceeded = results.every((r) => r.status === "fulfilled")
|
||||||
|
const stations = Array.from(stationMap.values())
|
||||||
|
|
||||||
|
if (allSucceeded) {
|
||||||
|
this.stationsCache = stations
|
||||||
|
}
|
||||||
|
|
||||||
|
return stations
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ export class TflSource implements FeedSource<TflAlertFeedItem> {
|
|||||||
throw new Error("Either client or apiKey must be provided")
|
throw new Error("Either client or apiKey must be provided")
|
||||||
}
|
}
|
||||||
this.client = options.client ?? new TflApi(options.apiKey!)
|
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<Record<string, ActionDefinition>> {
|
async listActions(): Promise<Record<string, ActionDefinition>> {
|
||||||
|
|||||||
Reference in New Issue
Block a user