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