mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-06 03:14:00 +00:00
End the data startup wait when the application is torn down during a slow layer attachment
This commit is contained in:
1 parent
7fb11507d5
commit
cf6d04b7db
2 files changed
+85
-15
No files matched your search
@@ -256,3 +256,45 @@ test('a catalog for an engine gives stand-ins only for the layers it leaves out'
|
||||
/Control layer missing from catalog: traffic/,
|
||||
);
|
||||
});
|
||||
|
||||
test('a teardown during startup ends the wait for a stalled layer attachment', async (t) => {
|
||||
const previous = globalThis.document;
|
||||
globalThis.document = { getElementById: () => null };
|
||||
t.after(() => {
|
||||
if (previous === undefined) delete globalThis.document;
|
||||
else globalThis.document = previous;
|
||||
});
|
||||
const layer = {
|
||||
id: 'slow',
|
||||
init: () => true,
|
||||
enable: () => true,
|
||||
update: () => true,
|
||||
disable: () => true,
|
||||
destroy: () => true,
|
||||
attachRenderer: (viewer) =>
|
||||
viewer?.second ? new Promise(() => {}) : undefined,
|
||||
detachRenderer() {},
|
||||
};
|
||||
const layerSession = { lifetime: new AbortController() };
|
||||
const start = (viewer, signal = null) => {
|
||||
const releases = [];
|
||||
const data = createApplicationData({
|
||||
scene: { viewer },
|
||||
controls: { styleManager: { attachDataManager() {} } },
|
||||
catalog: createLayerCatalog([layer], metadata([layer])),
|
||||
layerSession,
|
||||
signal,
|
||||
defer: (release) => releases.push(release),
|
||||
});
|
||||
return { data, releases };
|
||||
};
|
||||
const first = start({ first: true });
|
||||
assert.equal(await layerSession.manager.setEnabled('slow', true), true);
|
||||
for (const release of first.releases.reverse()) await release();
|
||||
|
||||
const application = new AbortController();
|
||||
const second = start({ second: true }, application.signal);
|
||||
application.abort();
|
||||
const { dataManager } = await second.data;
|
||||
assert.equal(dataManager, layerSession.manager);
|
||||
});
|
||||
+43
-15
@@ -11,17 +11,20 @@ export function createApplicationData({
|
||||
layerSession,
|
||||
onData,
|
||||
defer,
|
||||
signal = null,
|
||||
}) {
|
||||
// Initialize data layer manager
|
||||
// The modules get { signal, engine } on every call (viewer null on Navara).
|
||||
const dataManager = layerSession?.manager ?? new LayerLifecycle(viewer, {
|
||||
engine,
|
||||
allowQaRegistration,
|
||||
// A panel's host may report it hidden while it is on screen; its layers
|
||||
// keep polling (see keepPanelRendering in embed.js).
|
||||
visibilityTarget: panelAwareVisibility(document),
|
||||
getSourceAvailability: catalog?.getSourceAvailability,
|
||||
});
|
||||
const dataManager =
|
||||
layerSession?.manager ??
|
||||
new LayerLifecycle(viewer, {
|
||||
engine,
|
||||
allowQaRegistration,
|
||||
// A panel's host may report it hidden while it is on screen; its layers
|
||||
// keep polling (see keepPanelRendering in embed.js).
|
||||
visibilityTarget: panelAwareVisibility(document),
|
||||
getSourceAvailability: catalog?.getSourceAvailability,
|
||||
});
|
||||
if (layerSession) layerSession.manager = dataManager;
|
||||
defer(async () => {
|
||||
if (layerSession && !layerSession.lifetime.signal.aborted) {
|
||||
@@ -34,12 +37,15 @@ export function createApplicationData({
|
||||
`Data layers could not be destroyed: ${[...dataManager.layers.keys()].join(', ')}`,
|
||||
);
|
||||
});
|
||||
const presentation = layerSession?.presentation ?? new LayerPresentation(dataManager, {
|
||||
weatherClock: catalog?.weatherClock,
|
||||
});
|
||||
const presentation =
|
||||
layerSession?.presentation ??
|
||||
new LayerPresentation(dataManager, {
|
||||
weatherClock: catalog?.weatherClock,
|
||||
});
|
||||
if (layerSession) layerSession.presentation = presentation;
|
||||
defer(() => {
|
||||
if (layerSession && !layerSession.lifetime.signal.aborted) presentation.suspend();
|
||||
if (layerSession && !layerSession.lifetime.signal.aborted)
|
||||
presentation.suspend();
|
||||
else presentation.destroy();
|
||||
});
|
||||
onData?.(dataManager);
|
||||
@@ -47,7 +53,9 @@ export function createApplicationData({
|
||||
throw new TypeError('An application layer catalog is required');
|
||||
for (const layer of catalog.layers)
|
||||
layer.attachMapStackController?.(mapStackController);
|
||||
const attached = dataManager.bindCatalog(viewer, engine, catalog, { waitForCameraRestore: layerSession?.restoringView === true });
|
||||
const attached = dataManager.bindCatalog(viewer, engine, catalog, {
|
||||
waitForCameraRestore: layerSession?.restoringView === true,
|
||||
});
|
||||
for (const layer of catalog.layers) layer.attachDataManager?.(dataManager);
|
||||
|
||||
if (allowQaRegistration) {
|
||||
@@ -70,11 +78,31 @@ export function createApplicationData({
|
||||
delete window.__gevQaUnregisterLayer;
|
||||
});
|
||||
}
|
||||
presentation.mount(document.getElementById('data-toggles'), catalog.weatherClock);
|
||||
presentation.mount(
|
||||
document.getElementById('data-toggles'),
|
||||
catalog.weatherClock,
|
||||
);
|
||||
styleManager.attachDataManager(dataManager);
|
||||
// The sonar scene draws on the viewer; the Navara engine has none.
|
||||
if (viewer) defer(createCyberSonarScene(viewer, dataManager));
|
||||
|
||||
const data = { dataManager, catalog, presentation };
|
||||
return attached ? attached.then(() => data) : data;
|
||||
if (!attached) return data;
|
||||
// A teardown during startup must not wait for slow layer attachments: it
|
||||
// ends this wait, and the data cleanup above releases the scene.
|
||||
return new Promise((resolve, reject) => {
|
||||
const onAbort = () => resolve(data);
|
||||
if (signal?.aborted) onAbort();
|
||||
else signal?.addEventListener('abort', onAbort, { once: true });
|
||||
attached.then(
|
||||
() => {
|
||||
signal?.removeEventListener('abort', onAbort);
|
||||
resolve(data);
|
||||
},
|
||||
(error) => {
|
||||
signal?.removeEventListener('abort', onAbort);
|
||||
reject(error);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user