fix(cockpit): one place lookup that loads several packs reads as one load, not a LOAD COMPLETE between packs

This commit is contained in:
Sameh Khamis committed 2026-11-08 19:57:28 -08:00
1 parent f6dc89b4fa
commit c5e1951f51
2 files changed
+38 -2

No files matched your search

+24 -2
View File
@@ -50,6 +50,11 @@ const PACKS = {
/** The packs on their way now, and those whose last load failed. */
const loadingPacks = new Set();
const failedPacks = new Set();
// One lookup loads its packs one after another (countries and seas, then
// divisions, then places): the status holds them as one load until the
// lookup ends, rather than ending and starting a batch between packs.
let lookupsInFlight = 0;
let lookupLoaded = false;
const loadingListeners = new Set();
function notifyLoading() {
@@ -74,6 +79,7 @@ export function reportedPlacePackLoad(name, load) {
return async () => {
// A retry is a fresh try: its batch ends on what this load does.
failedPacks.delete(name);
if (lookupsInFlight > 0) lookupLoaded = true;
loadingPacks.add(name);
notifyLoading();
try {
@@ -97,7 +103,10 @@ export function reportedPlacePackLoad(name, load) {
* @returns {{loading: boolean, failed: boolean}}
*/
export function placePacksStatus() {
return { loading: loadingPacks.size > 0, failed: failedPacks.size > 0 };
return {
loading: loadingPacks.size > 0 || (lookupLoaded && lookupsInFlight > 0),
failed: failedPacks.size > 0,
};
}
/**
@@ -324,7 +333,20 @@ async function orNull(lookup) {
* simplification) or it is invalid. Rejects only when the country and
* marine packs fail.
*/
export async function placeBelow(
export async function placeBelow(latitude, longitude, options) {
lookupsInFlight += 1;
try {
return await findPlaceBelow(latitude, longitude, options);
} finally {
lookupsInFlight -= 1;
if (lookupsInFlight === 0 && lookupLoaded) {
lookupLoaded = false;
notifyLoading();
}
}
}
async function findPlaceBelow(
latitude,
longitude,
{ nearKm = null, detail = DETAIL_LOOKUPS } = {},
+14
View File
@@ -41,3 +41,17 @@ test('a pack that would not load stays failed until it loads', async () => {
assert.equal(await retry, 1);
assert.deepEqual(place.placePacksStatus(), { loading: false, failed: false });
});
test('one lookup that loads several packs reads as one load', async () => {
const place = await import('./placeBelow.js?one-lookup');
const heard = [];
const stop = place.onPlacePacksLoadingChange(() => {
const { loading } = place.placePacksStatus();
if (heard.at(-1) !== loading) heard.push(loading);
});
// On land with a radius: countries and seas, then divisions, then places.
const found = await place.placeBelow(48.86, 2.35, { nearKm: 50 });
assert.equal(found.near, 'Paris');
assert.deepEqual(heard, [true, false], 'no gap between the packs');
stop();
});