Skip to content

Commit 322543c

Browse files
committed
Improve connection handling
1 parent ce8e6cb commit 322543c

File tree

4 files changed

+59
-17
lines changed

4 files changed

+59
-17
lines changed

eca-webview

src/bridge/outbound-handler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export interface OutboundContext {
2626
/** Triggers initial state dispatch (called on webview/ready). */
2727
dispatchInitialState: () => Promise<void>;
2828
/** Lazy-load messages for a chat (fetches from server if not yet loaded). */
29-
loadChatMessages: (chatId: string) => Promise<void>;
29+
loadChatMessages: (chatId: string) => Promise<boolean>;
3030
}
3131

3232
/**

src/bridge/transport.ts

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -763,15 +763,44 @@ export class WebBridge {
763763
});
764764
}
765765

766-
// Auto-select the preferred chat (from previous session) or fall back
767-
// to the most recent chat in the list.
766+
// Build a priority-ordered list of chats to try loading.
767+
// Preferred (from previous session) comes first, then most-recent-first.
768+
const candidates: ChatSummary[] = [];
768769
const preferred = this.preferredChatId
769770
? summaries.find((s) => s.id === this.preferredChatId)
770771
: null;
771-
const chatToSelect = preferred ?? summaries[summaries.length - 1];
772-
if (chatToSelect?.id) {
773-
this.currentChatId = chatToSelect.id;
774-
await this.loadChatMessages(chatToSelect.id);
772+
if (preferred) candidates.push(preferred);
773+
// Add remaining summaries in reverse order (most recent first), skipping preferred.
774+
for (let i = summaries.length - 1; i >= 0; i--) {
775+
if (summaries[i].id !== preferred?.id) {
776+
candidates.push(summaries[i]);
777+
}
778+
}
779+
780+
// Try each candidate until one loads successfully.
781+
let loaded = false;
782+
for (const candidate of candidates) {
783+
if (!candidate?.id) continue;
784+
this.currentChatId = candidate.id;
785+
if (await this.loadChatMessages(candidate.id)) {
786+
// Clear stale preferred if we had to fall back to a different chat.
787+
if (preferred && candidate.id !== preferred.id) {
788+
console.log(`[Bridge] Preferred chat ${this.preferredChatId} no longer exists, fell back to ${candidate.id}`);
789+
this.preferredChatId = null;
790+
}
791+
loaded = true;
792+
break;
793+
}
794+
// Chat doesn't exist on the server — remove its stale sidebar entry.
795+
console.warn(`[Bridge] Chat ${candidate.id} failed to load, removing from sidebar`);
796+
this.removeChatEntry(candidate.id);
797+
}
798+
799+
// If nothing loaded, clear stale preferred and reset current chat so
800+
// the webview shows a clean welcome screen instead of a ghost entry.
801+
if (!loaded) {
802+
this.currentChatId = null;
803+
this.preferredChatId = null;
775804
}
776805

777806
this.notifyChatListChange();
@@ -787,9 +816,12 @@ export class WebBridge {
787816
*
788817
* Called automatically on initial connect (for the most recent chat)
789818
* and on demand when the user switches chats.
819+
*
820+
* @returns `true` if the chat was successfully loaded (or was already loaded),
821+
* `false` if loading failed (e.g. chat deleted, server error).
790822
*/
791-
async loadChatMessages(chatId: string): Promise<void> {
792-
if (this.loadedChatIds.has(chatId)) return;
823+
async loadChatMessages(chatId: string): Promise<boolean> {
824+
if (this.loadedChatIds.has(chatId)) return true;
793825

794826
try {
795827
console.log(`[Bridge] Loading messages for chat ${chatId}`);
@@ -803,7 +835,7 @@ export class WebBridge {
803835
} else {
804836
// Cache miss — fetch from server with one retry on failure
805837
chat = await this.fetchChatWithRetry(chatId);
806-
if (!chat) return; // Both attempts failed
838+
if (!chat) return false; // Both attempts failed
807839

808840
// Populate cache for future use
809841
messageCache.set(this.host, chatId, chat);
@@ -838,19 +870,27 @@ export class WebBridge {
838870
this.dispatch('chat/batchContentReceived', events);
839871

840872
console.log(`[Bridge] Restored ${chat?.messages?.length ?? 0} message(s) for chat ${chatId}`);
873+
return true;
841874
} catch (err) {
842875
console.error(`[Bridge] Failed to load messages for chat ${chatId}:`, err);
876+
return false;
843877
}
844878
}
845879

846880
/**
847-
* Fetch a chat from the REST API with a single retry on failure.
848-
* Returns null if both attempts fail.
881+
* Fetch a chat from the REST API with a single retry on transient failures.
882+
* Does NOT retry on "does not exist" errors (404) — the chat is gone.
883+
* Returns null if the fetch ultimately fails.
849884
*/
850885
private async fetchChatWithRetry(chatId: string): Promise<import('./types').RemoteChat | null> {
851886
try {
852887
return await this.api.getChat(chatId);
853-
} catch (err) {
888+
} catch (err: any) {
889+
// Don't retry on 404 — the chat is definitively gone
890+
if (err?.message?.includes('does not exist')) {
891+
console.warn(`[Bridge] Chat ${chatId} does not exist on the server`);
892+
return null;
893+
}
854894
console.warn(`[Bridge] First fetch failed for chat ${chatId}, retrying...`, err);
855895
try {
856896
return await this.api.getChat(chatId);

src/pages/RemoteProduct.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -271,12 +271,14 @@ export function RemoteProduct() {
271271
setChatEntries(entries);
272272
setSelectedChatId(selected);
273273
// Persist the last viewed chat ID so it can be restored on reconnect.
274-
if (connId && selected) {
274+
// When selected is null (all chats failed to load), clear the stale
275+
// lastChatId so it doesn't keep 404-ing on every subsequent connect.
276+
if (connId) {
275277
setEntries((prev) => {
276278
const entry = prev.find((e) => e.id === connId);
277-
if (entry?.lastChatId === selected) return prev; // no change — keep same reference
279+
if ((entry?.lastChatId ?? null) === (selected ?? null)) return prev;
278280
return prev.map((e) =>
279-
e.id === connId ? { ...e, lastChatId: selected } : e,
281+
e.id === connId ? { ...e, lastChatId: selected ?? undefined } : e,
280282
);
281283
});
282284
}

0 commit comments

Comments
 (0)