Limit city detail fallback to batch failures
This commit is contained in:
@@ -118,6 +118,12 @@ export async function runTests() {
|
||||
flushCityDetailBatchBlock.includes("payload?.partial === true"),
|
||||
"partial detail-batch misses should resolve without immediately issuing single-city fallback requests",
|
||||
);
|
||||
assert(
|
||||
flushCityDetailBatchBlock.includes("if (!payload)") &&
|
||||
flushCityDetailBatchBlock.includes("resolveCityDetailBatchWithSingleFallback") &&
|
||||
flushCityDetailBatchBlock.includes("resolveBatchWaiters(waiters, null)"),
|
||||
"single-city detail fallback should be reserved for whole-batch failures rather than successful batch misses",
|
||||
);
|
||||
const fetchHourlyBlock = chartLogicSource.match(/async function fetchHourlyForecastForCity[\s\S]*?\r?\n}\r?\n\r?\nfunction fetchCityDetailWithTimeout/)?.[0] || "";
|
||||
assert(
|
||||
fetchHourlyBlock.includes("queueCityDetailBatch(city, resParam)") &&
|
||||
|
||||
@@ -1118,6 +1118,11 @@ async function flushCityDetailBatch(resolution: string) {
|
||||
|
||||
try {
|
||||
const payload = await fetchCityDetailBatchWithTimeout(cities, resolution);
|
||||
if (!payload) {
|
||||
await resolveCityDetailBatchWithSingleFallback(cities, queue, resolution);
|
||||
return;
|
||||
}
|
||||
|
||||
const details = payload?.details || {};
|
||||
const partialMissingCities =
|
||||
payload?.partial === true
|
||||
@@ -1136,33 +1141,35 @@ async function flushCityDetailBatch(resolution: string) {
|
||||
resolveBatchWaiters(waiters, null);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
resolveBatchWaiters(
|
||||
waiters,
|
||||
await runQueuedHourlyDetailRequest(() => fetchSingleHourlyForecastForCity(city, resolution)),
|
||||
);
|
||||
} catch (error) {
|
||||
rejectBatchWaiters(waiters, error);
|
||||
}
|
||||
resolveBatchWaiters(waiters, null);
|
||||
}),
|
||||
);
|
||||
} catch (error) {
|
||||
await Promise.all(
|
||||
cities.map(async (city) => {
|
||||
const waiters = queue.waiters.get(city);
|
||||
try {
|
||||
resolveBatchWaiters(
|
||||
waiters,
|
||||
await runQueuedHourlyDetailRequest(() => fetchSingleHourlyForecastForCity(city, resolution)),
|
||||
);
|
||||
} catch (fallbackError) {
|
||||
rejectBatchWaiters(waiters, fallbackError || error);
|
||||
}
|
||||
}),
|
||||
);
|
||||
await resolveCityDetailBatchWithSingleFallback(cities, queue, resolution, error);
|
||||
}
|
||||
}
|
||||
|
||||
async function resolveCityDetailBatchWithSingleFallback(
|
||||
cities: string[],
|
||||
queue: CityDetailBatchQueue,
|
||||
resolution: string,
|
||||
reason?: unknown,
|
||||
) {
|
||||
await Promise.all(
|
||||
cities.map(async (city) => {
|
||||
const waiters = queue.waiters.get(city);
|
||||
try {
|
||||
resolveBatchWaiters(
|
||||
waiters,
|
||||
await runQueuedHourlyDetailRequest(() => fetchSingleHourlyForecastForCity(city, resolution)),
|
||||
);
|
||||
} catch (fallbackError) {
|
||||
rejectBatchWaiters(waiters, fallbackError || reason);
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
function fetchCityDetailBatchWithTimeout(cities: string[], resolution: string) {
|
||||
const controller = new AbortController();
|
||||
const timeoutId = globalThis.setTimeout(() => controller.abort(), HOURLY_DETAIL_REQUEST_TIMEOUT_MS);
|
||||
|
||||
Reference in New Issue
Block a user