mirror of
https://github.com/block/buzz.git
synced 2026-11-10 11:21:05 +00:00
fix(desktop): invalidate stale media lookups
Co-authored-by: npub1qvn3cujt28pg06ehlstrxyz6ayzp06t4uc7r566vxwwgrv24hglq9zju0n <03271c724b51c287eb37fc1633105ae90417e975e63c3a6b4c339c81b155ba3e@sprout-oss.stage.blox.sqprod.co> Signed-off-by: npub1qvn3cujt28pg06ehlstrxyz6ayzp06t4uc7r566vxwwgrv24hglq9zju0n <03271c724b51c287eb37fc1633105ae90417e975e63c3a6b4c339c81b155ba3e@sprout-oss.stage.blox.sqprod.co>
This commit is contained in:
parent
43bd104de5
commit
c6345f79bf
@@ -5,9 +5,62 @@ import { mediaProxyUrl } from "./mediaUrl.ts";
|
||||
|
||||
const HASH = "a".repeat(64);
|
||||
|
||||
function deferred() {
|
||||
let resolve;
|
||||
const promise = new Promise((resolvePromise) => {
|
||||
resolve = resolvePromise;
|
||||
});
|
||||
return { promise, resolve };
|
||||
}
|
||||
|
||||
test("mediaProxyUrl: uses the IPv4 loopback literal for the localhost proxy", () => {
|
||||
assert.equal(
|
||||
mediaProxyUrl(54321, `${HASH}.png`),
|
||||
`http://127.0.0.1:54321/media/${HASH}.png`,
|
||||
);
|
||||
});
|
||||
|
||||
test("resetMediaCaches: ignores relay origin lookups from the previous generation", async () => {
|
||||
const previousWindow = globalThis.window;
|
||||
const staleOrigin = deferred();
|
||||
let relayOriginCalls = 0;
|
||||
|
||||
globalThis.window = {
|
||||
__TAURI_INTERNALS__: {
|
||||
invoke(command) {
|
||||
if (command === "get_media_proxy_port") return Promise.resolve(54321);
|
||||
if (command === "get_relay_http_url") {
|
||||
relayOriginCalls += 1;
|
||||
return relayOriginCalls === 1
|
||||
? staleOrigin.promise
|
||||
: Promise.resolve("https://active.example");
|
||||
}
|
||||
return Promise.reject(new Error(`Unexpected command: ${command}`));
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
try {
|
||||
// A unique URL triggers module-load fetching with the stale relay lookup
|
||||
// still unresolved, matching a cold launch before applyCommunity finishes.
|
||||
const mediaUrl = await import(`./mediaUrl.ts?race=${Date.now()}`);
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
|
||||
mediaUrl.resetMediaCaches();
|
||||
const activeUrl = `https://active.example/media/${HASH}.png`;
|
||||
mediaUrl.rewriteRelayUrl(activeUrl);
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
|
||||
// Complete the old lookup after reset. It must not overwrite the active
|
||||
// community origin fetched by the new generation.
|
||||
staleOrigin.resolve("https://stale.example");
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
|
||||
assert.equal(
|
||||
mediaUrl.rewriteRelayUrl(activeUrl),
|
||||
`http://127.0.0.1:54321/media/${HASH}.png`,
|
||||
);
|
||||
} finally {
|
||||
globalThis.window = previousWindow;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -29,6 +29,13 @@ let portPromise: Promise<number | null> | null = null;
|
||||
/** Cached relay origin (e.g. "https://buzz-oss.stage.blox.sqprod.co"). */
|
||||
let cachedRelayOrigin: string | null = null;
|
||||
|
||||
/**
|
||||
* Monotonic cache generation. Async lookups capture the current generation and
|
||||
* may only publish results while it is still current. This prevents a lookup
|
||||
* started for the previous community from repopulating caches after reset.
|
||||
*/
|
||||
let cacheGeneration = 0;
|
||||
|
||||
const POLL_INTERVAL_MS = 100;
|
||||
const POLL_TIMEOUT_MS = 5000;
|
||||
|
||||
@@ -38,20 +45,25 @@ const POLL_TIMEOUT_MS = 5000;
|
||||
* Returns the port, or null if the proxy never came up.
|
||||
*/
|
||||
async function fetchProxyPort(): Promise<number | null> {
|
||||
const generation = cacheGeneration;
|
||||
|
||||
// Fetch relay origin in parallel — fire-and-forget, no retry needed.
|
||||
if (!cachedRelayOrigin) {
|
||||
invoke<string>("get_relay_http_url")
|
||||
.then((url) => {
|
||||
cachedRelayOrigin = url.replace(/\/+$/, "");
|
||||
if (generation === cacheGeneration) {
|
||||
cachedRelayOrigin = url.replace(/\/+$/, "");
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
|
||||
const deadline = Date.now() + POLL_TIMEOUT_MS;
|
||||
while (Date.now() < deadline) {
|
||||
while (Date.now() < deadline && generation === cacheGeneration) {
|
||||
try {
|
||||
const port = await invoke<number>("get_media_proxy_port");
|
||||
if (port > 0) {
|
||||
if (generation !== cacheGeneration) return null;
|
||||
cachedPort = port;
|
||||
return port;
|
||||
}
|
||||
@@ -75,6 +87,7 @@ if (typeof window !== "undefined") {
|
||||
* and relay origin for the new community.
|
||||
*/
|
||||
export function resetMediaCaches(): void {
|
||||
cacheGeneration += 1;
|
||||
cachedPort = null;
|
||||
portPromise = null;
|
||||
cachedRelayOrigin = null;
|
||||
|
||||
Reference in New Issue
Block a user