fix: collab overlay stuck on 'Connecting' — init race + timeout
- Runtime now sets isInitialized after IndexedDB (before WS connect) so the overlay can detect it within ~500ms instead of waiting 30s+ - Overlay no longer gives up polling after 15s (slows to 2s instead) - Overlay subscribes to runtime onConnect/onDisconnect for live updates Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
6a0ad06c11
commit
28bfa37199
|
|
@ -121,6 +121,8 @@ export class RStackCollabOverlay extends HTMLElement {
|
||||||
}
|
}
|
||||||
if (this.#gcInterval) clearInterval(this.#gcInterval);
|
if (this.#gcInterval) clearInterval(this.#gcInterval);
|
||||||
this.#gcInterval = null;
|
this.#gcInterval = null;
|
||||||
|
if (this.#runtimePollInterval) clearInterval(this.#runtimePollInterval);
|
||||||
|
this.#runtimePollInterval = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Public bridge API (for canvas CommunitySync) ──
|
// ── Public bridge API (for canvas CommunitySync) ──
|
||||||
|
|
@ -171,21 +173,36 @@ export class RStackCollabOverlay extends HTMLElement {
|
||||||
|
|
||||||
// ── Runtime connection ──
|
// ── Runtime connection ──
|
||||||
|
|
||||||
|
#runtimePollInterval: ReturnType<typeof setInterval> | null = null;
|
||||||
|
|
||||||
#tryConnect() {
|
#tryConnect() {
|
||||||
const runtime = (window as any).__rspaceOfflineRuntime;
|
const runtime = (window as any).__rspaceOfflineRuntime;
|
||||||
if (runtime?.isInitialized) {
|
if (runtime?.isInitialized) {
|
||||||
this.#onRuntimeReady(runtime);
|
this.#onRuntimeReady(runtime);
|
||||||
} else {
|
} else {
|
||||||
// Retry until runtime is ready
|
// Poll until runtime is ready (no timeout — WS connect can take 30s+)
|
||||||
const check = setInterval(() => {
|
let polls = 0;
|
||||||
|
this.#runtimePollInterval = setInterval(() => {
|
||||||
const rt = (window as any).__rspaceOfflineRuntime;
|
const rt = (window as any).__rspaceOfflineRuntime;
|
||||||
if (rt?.isInitialized) {
|
if (rt?.isInitialized) {
|
||||||
clearInterval(check);
|
clearInterval(this.#runtimePollInterval!);
|
||||||
|
this.#runtimePollInterval = null;
|
||||||
this.#onRuntimeReady(rt);
|
this.#onRuntimeReady(rt);
|
||||||
}
|
}
|
||||||
|
// Slow down after 15s (30 polls × 500ms) to reduce overhead
|
||||||
|
polls++;
|
||||||
|
if (polls === 30 && this.#runtimePollInterval) {
|
||||||
|
clearInterval(this.#runtimePollInterval);
|
||||||
|
this.#runtimePollInterval = setInterval(() => {
|
||||||
|
const rt2 = (window as any).__rspaceOfflineRuntime;
|
||||||
|
if (rt2?.isInitialized) {
|
||||||
|
clearInterval(this.#runtimePollInterval!);
|
||||||
|
this.#runtimePollInterval = null;
|
||||||
|
this.#onRuntimeReady(rt2);
|
||||||
|
}
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
}, 500);
|
}, 500);
|
||||||
// Give up after 15s
|
|
||||||
setTimeout(() => clearInterval(check), 15000);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,11 @@ export class RSpaceOfflineRuntime {
|
||||||
// 1. Open IndexedDB
|
// 1. Open IndexedDB
|
||||||
await this.#store.open();
|
await this.#store.open();
|
||||||
|
|
||||||
// 2. Connect WebSocket (non-blocking — works offline)
|
// 2. Mark initialized early so UI components can start tracking state
|
||||||
|
// (WS connect can take 30s+ if the server is slow to respond)
|
||||||
|
this.#initialized = true;
|
||||||
|
|
||||||
|
// 3. Connect WebSocket (non-blocking — works offline)
|
||||||
const proto = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
const proto = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||||
const wsUrl = `${proto}//${location.host}/ws/${this.#activeSpace}`;
|
const wsUrl = `${proto}//${location.host}/ws/${this.#activeSpace}`;
|
||||||
|
|
||||||
|
|
@ -103,9 +107,7 @@ export class RSpaceOfflineRuntime {
|
||||||
this.#setStatus('offline');
|
this.#setStatus('offline');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#initialized = true;
|
// 4. Storage housekeeping (non-blocking)
|
||||||
|
|
||||||
// 3. Storage housekeeping (non-blocking)
|
|
||||||
this.#runStorageHousekeeping();
|
this.#runStorageHousekeeping();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.#setStatus('error');
|
this.#setStatus('error');
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue