mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-06 03:14:00 +00:00
fix(street-level): release superseded and unmounted Google viewer work (#1117)
A superseded open wait cleared the shared cancelShown slot that belonged to the newer wait, leaving its auth listener and timer alive after close; open() now settles the previous wait first. A lookup whose viewer unmounted while the Street View service loaded still sent a billed getPanorama; describe() now rechecks the lookup after acquisition.
This commit is contained in:
1 parent
3c3ea269a9
commit
fb10889841
4 files changed
+76
-1
No files matched your search
@@ -0,0 +1,3 @@
|
|||||||
|
- Release superseded Google Street View open waits and suppress metadata
|
||||||
|
requests whose viewer was unmounted while the service loaded (rudycelekli,
|
||||||
|
#1117).
|
||||||
@@ -3465,7 +3465,10 @@ controls (the address goes in the caption); a pose goes out at once and
|
|||||||
again when the panorama's month, photographer and address arrive (one
|
again when the panorama's month, photographer and address arrive (one
|
||||||
successful lookup per panorama per session, seeded by the nearest lookup;
|
successful lookup per panorama per session, seeded by the nearest lookup;
|
||||||
a details lookup that fails or takes over ten seconds waits five seconds
|
a details lookup that fails or takes over ten seconds waits five seconds
|
||||||
before a view event can retry, and an unmount drops lookups in flight). A key
|
before a view event can retry, and an unmount drops lookups in flight). Opening
|
||||||
|
another panorama settles the previous open before registering its wait; closing
|
||||||
|
then releases the current wait immediately. A details lookup released while its
|
||||||
|
service loads makes no panorama request after that service becomes available. A key
|
||||||
Google refuses (`gm_authFailure`: the API not enabled, a referrer it does
|
Google refuses (`gm_authFailure`: the API not enabled, a referrer it does
|
||||||
not allow, billing off) reads KEY REJECTED and fails a pending open at
|
not allow, billing off) reads KEY REJECTED and fails a pending open at
|
||||||
once; a lookup or open Google never answers fails after 10 or 20 s. In CI
|
once; a lookup or open Google never answers fails after 10 or 20 s. In CI
|
||||||
|
|||||||
@@ -97,6 +97,8 @@ export function createGoogleViewer({ loader, getService, render } = {}) {
|
|||||||
service ||= getService
|
service ||= getService
|
||||||
? await getService()
|
? await getService()
|
||||||
: new (await ensureLibrary()).StreetViewService();
|
: new (await ensureLibrary()).StreetViewService();
|
||||||
|
if (!current())
|
||||||
|
throw new Error('Street View details lookup was released');
|
||||||
return service.getPanorama({ pano: panoId });
|
return service.getPanorama({ pano: panoId });
|
||||||
})().then(resolve, reject);
|
})().then(resolve, reject);
|
||||||
});
|
});
|
||||||
@@ -236,6 +238,7 @@ export function createGoogleViewer({ loader, getService, render } = {}) {
|
|||||||
const panoId = String(imageId);
|
const panoId = String(imageId);
|
||||||
if (!host) throw new Error('Street View is not mounted');
|
if (!host) throw new Error('Street View is not mounted');
|
||||||
if (loader.authFailed()) throw new Error(KEY_REJECTED_MESSAGE);
|
if (loader.authFailed()) throw new Error(KEY_REJECTED_MESSAGE);
|
||||||
|
cancelShown?.();
|
||||||
pendingOpen = panoId;
|
pendingOpen = panoId;
|
||||||
const instance = await ensurePanorama(host);
|
const instance = await ensurePanorama(host);
|
||||||
if (pendingOpen !== panoId) return;
|
if (pendingOpen !== panoId) return;
|
||||||
|
|||||||
@@ -403,3 +403,69 @@ test('a remount looks up again a panorama whose lookup hung', async () => {
|
|||||||
await settle();
|
await settle();
|
||||||
assert.equal(poses.length, count);
|
assert.equal(poses.length, count);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('superseded panorama waits cannot steal the current close cleanup', async (t) => {
|
||||||
|
t.mock.timers.enable({ apis: ['setTimeout'] });
|
||||||
|
const { OPEN_TIMEOUT_MS } = await import('./policy.js');
|
||||||
|
const flush = async () => {
|
||||||
|
for (let i = 0; i < 10; i++) await Promise.resolve();
|
||||||
|
};
|
||||||
|
const { fake, loader, viewer, host } = setup();
|
||||||
|
await viewer.mount(host);
|
||||||
|
const [panorama] = fake.built;
|
||||||
|
panorama.setPano = (id) => {
|
||||||
|
panorama.pano = id;
|
||||||
|
};
|
||||||
|
const first = viewer.open('pano-a');
|
||||||
|
await flush();
|
||||||
|
const second = viewer.open('pano-b');
|
||||||
|
await flush();
|
||||||
|
panorama.fire('position_changed'); // new panorama has not reached OK
|
||||||
|
await flush();
|
||||||
|
viewer.close();
|
||||||
|
const remaining = loader.listenerCount();
|
||||||
|
t.mock.timers.tick(OPEN_TIMEOUT_MS);
|
||||||
|
await Promise.allSettled([first, second]);
|
||||||
|
assert.equal(
|
||||||
|
remaining,
|
||||||
|
0,
|
||||||
|
'close disposes every pending open without waiting 20 seconds',
|
||||||
|
);
|
||||||
|
assert.equal(panorama.visible, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('unmount during details-service acquisition makes no later billed lookup', async () => {
|
||||||
|
const fake = fakeStreetViewLibrary({ panoramas: PANORAMAS });
|
||||||
|
const loader = fakeMapsLoader(fake.library);
|
||||||
|
const { createGoogleProvider } = await import('./index.js');
|
||||||
|
let release;
|
||||||
|
const acquiring = new Promise((resolve) => {
|
||||||
|
release = resolve;
|
||||||
|
});
|
||||||
|
const importLibrary = loader.importLibrary.bind(loader);
|
||||||
|
let imports = 0;
|
||||||
|
loader.importLibrary = async (name) => {
|
||||||
|
if (++imports > 1) await acquiring;
|
||||||
|
return importLibrary(name);
|
||||||
|
};
|
||||||
|
const provider = createGoogleProvider({
|
||||||
|
getApiKey: () => 'fixture-key',
|
||||||
|
loader,
|
||||||
|
});
|
||||||
|
const instance = provider.create({
|
||||||
|
notify() {},
|
||||||
|
actions: { reportError() {} },
|
||||||
|
});
|
||||||
|
const viewer = instance.viewer;
|
||||||
|
await viewer.mount(fakeHost());
|
||||||
|
await viewer.open('pano-a');
|
||||||
|
viewer.unmount();
|
||||||
|
release();
|
||||||
|
for (let i = 0; i < 10; i++) await Promise.resolve();
|
||||||
|
assert.equal(
|
||||||
|
fake.lookups.length,
|
||||||
|
0,
|
||||||
|
'teardown invalidates the request before calling getPanorama',
|
||||||
|
);
|
||||||
|
instance.destroy();
|
||||||
|
});
|
||||||
Reference in new issue
Block a user