From 9a0f1a4879e42a163178119cb1a2c619963fa7c5 Mon Sep 17 00:00:00 2001 From: sid597 Date: Fri, 31 Oct 2025 21:29:18 +0530 Subject: [PATCH 1/3] remove success banner for suggestive mode, send error email on fail, fix on load check if we need to initialize by default --- apps/roam/src/index.ts | 16 ++++++- apps/roam/src/utils/syncDgNodesToSupabase.ts | 50 ++++++++++++-------- 2 files changed, 44 insertions(+), 22 deletions(-) diff --git a/apps/roam/src/index.ts b/apps/roam/src/index.ts index 84a2050e9..8e7a94389 100644 --- a/apps/roam/src/index.ts +++ b/apps/roam/src/index.ts @@ -1,4 +1,4 @@ -import { addStyle } from "roamjs-components/dom"; +import { addStyle, getRoamUrl } from "roamjs-components/dom"; import { render as renderToast } from "roamjs-components/components/Toast"; import getCurrentUserUid from "roamjs-components/queries/getCurrentUserUid"; import { runExtension } from "roamjs-components/util"; @@ -32,6 +32,7 @@ import { setSyncActivity, } from "./utils/syncDgNodesToSupabase"; import { initPluginTimer } from "./utils/pluginTimer"; +import { createClient } from "@repo/database/lib/client"; const initPostHog = () => { posthog.init("phc_SNMmBqwNfcEpNduQ41dBUjtGNEUEKAy6jTn63Fzsrax", { @@ -126,7 +127,18 @@ export default runExtension(async (onloadArgs) => { document.addEventListener("input", discourseNodeSearchTriggerListener); document.addEventListener("selectionchange", nodeCreationPopoverListener); - await initializeSupabaseSync(); + const supabase = createClient(); + if (supabase) { + const { data } = await supabase + .from("Space") + .select("url") + .eq("url", getRoamUrl()) + .maybeSingle(); + + if (data) { + initializeSupabaseSync(); + } + } const { extensionAPI } = onloadArgs; window.roamjs.extension.queryBuilder = { diff --git a/apps/roam/src/utils/syncDgNodesToSupabase.ts b/apps/roam/src/utils/syncDgNodesToSupabase.ts index 2eda5bb71..b3814528c 100644 --- a/apps/roam/src/utils/syncDgNodesToSupabase.ts +++ b/apps/roam/src/utils/syncDgNodesToSupabase.ts @@ -18,10 +18,10 @@ import { } from "./conceptConversion"; import { fetchEmbeddingsForNodes } from "./upsertNodesAsContentWithEmbeddings"; import { convertRoamNodeToLocalContent } from "./upsertNodesAsContentWithEmbeddings"; -import { render as renderToast } from "roamjs-components/components/Toast"; import { createClient, type DGSupabaseClient } from "@repo/database/lib/client"; import type { Json, CompositeTypes, Enums } from "@repo/database/dbTypes"; - +import { render as renderToast } from "roamjs-components/components/Toast"; +import sendErrorEmail from "~/utils/sendErrorEmail"; type LocalContentDataInput = Partial>; type AccountLocalInput = CompositeTypes<"account_local_input">; @@ -63,40 +63,50 @@ export const endSyncTask = async ( }); if (error) { console.error("endSyncTask: Error calling end_sync_task:", error); - if (showToast) + if (showToast) { renderToast({ id: "discourse-embedding-error", content: "Failed to complete discourse node embeddings sync", intent: "danger", timeout: 5000, }); + sendErrorEmail({ + error: new Error("Discourse node embeddings sync failed"), + type: "Sync Failed", + context: { status }, + }).catch(() => {}); + } return; } else if (showToast) { - if (status === "complete") { - renderToast({ - id: "discourse-embedding-complete", - content: "Successfully completed discourse node embeddings sync", - intent: "success", - timeout: 4000, - }); - } else if (status === "failed") { + if (status === "failed") { renderToast({ id: "discourse-embedding-failed", content: "Discourse node embeddings sync failed", intent: "danger", timeout: 5000, }); + sendErrorEmail({ + error: new Error("Discourse node embeddings sync failed"), + type: "Sync Failed", + context: { status }, + }).catch(() => {}); } } } catch (error) { console.error("endSyncTask: Error calling end_sync_task:", error); - if (showToast) + if (showToast) { renderToast({ id: "discourse-embedding-error", content: "Failed to complete discourse node embeddings sync", intent: "danger", timeout: 5000, }); + sendErrorEmail({ + error: new Error("Failed to complete discourse node embeddings sync"), + type: "Sync Failed", + context: { status }, + }).catch(() => {}); + } } }; @@ -468,13 +478,13 @@ export const createOrUpdateDiscourseEmbedding = async (showToast = false) => { } }; -export const initializeSupabaseSync = async () => { - const supabase = createClient(); - if (supabase === null) { - doSync = false; - } else { - doSync = true; - // eslint-disable-next-line @typescript-eslint/no-misused-promises - activeTimeout = setTimeout(createOrUpdateDiscourseEmbedding, 100, true); +export const initializeSupabaseSync = (): void => { + if (activeTimeout !== null) { + clearTimeout(activeTimeout); + activeTimeout = null; } + + doSync = true; + // eslint-disable-next-line @typescript-eslint/no-misused-promises + activeTimeout = setTimeout(createOrUpdateDiscourseEmbedding, 100, true); }; From 9c0d7581316b40738d6c2e851ba436a846a2d496 Mon Sep 17 00:00:00 2001 From: sid597 Date: Fri, 31 Oct 2025 22:11:48 +0530 Subject: [PATCH 2/3] address coderabbit review --- apps/roam/src/utils/syncDgNodesToSupabase.ts | 26 +++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/apps/roam/src/utils/syncDgNodesToSupabase.ts b/apps/roam/src/utils/syncDgNodesToSupabase.ts index b3814528c..fe63f368f 100644 --- a/apps/roam/src/utils/syncDgNodesToSupabase.ts +++ b/apps/roam/src/utils/syncDgNodesToSupabase.ts @@ -70,12 +70,13 @@ export const endSyncTask = async ( intent: "danger", timeout: 5000, }); - sendErrorEmail({ - error: new Error("Discourse node embeddings sync failed"), - type: "Sync Failed", - context: { status }, - }).catch(() => {}); } + sendErrorEmail({ + error: new Error("Failed to complete discourse node embeddings sync"), + type: "Sync Failed", + context: { status }, + }).catch(() => {}); + return; } else if (showToast) { if (status === "failed") { @@ -85,11 +86,6 @@ export const endSyncTask = async ( intent: "danger", timeout: 5000, }); - sendErrorEmail({ - error: new Error("Discourse node embeddings sync failed"), - type: "Sync Failed", - context: { status }, - }).catch(() => {}); } } } catch (error) { @@ -101,12 +97,12 @@ export const endSyncTask = async ( intent: "danger", timeout: 5000, }); - sendErrorEmail({ - error: new Error("Failed to complete discourse node embeddings sync"), - type: "Sync Failed", - context: { status }, - }).catch(() => {}); } + sendErrorEmail({ + error: new Error("Failed to complete discourse node embeddings sync"), + type: "Sync Failed", + context: { status }, + }).catch(() => {}); } }; From a879a5cfadeb7d1ce8b6dcbad79fef2227d7bb29 Mon Sep 17 00:00:00 2001 From: sid597 Date: Sun, 2 Nov 2025 10:00:54 +0530 Subject: [PATCH 3/3] address review --- apps/roam/src/utils/syncDgNodesToSupabase.ts | 64 ++++++++++++-------- 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/apps/roam/src/utils/syncDgNodesToSupabase.ts b/apps/roam/src/utils/syncDgNodesToSupabase.ts index fe63f368f..e155f25bd 100644 --- a/apps/roam/src/utils/syncDgNodesToSupabase.ts +++ b/apps/roam/src/utils/syncDgNodesToSupabase.ts @@ -42,6 +42,31 @@ type SyncTaskInfo = { shouldProceed: boolean; }; +const notifyEndSyncFailure = ({ + status, + showToast, + reason, +}: { + status: Enums<"task_status">; + showToast: boolean; + reason: string; +}): void => { + if (showToast) { + renderToast({ + id: "discourse-embedding-error", + content: "Failed to complete discourse node embeddings sync", + intent: "danger", + timeout: 5000, + }); + } + + sendErrorEmail({ + error: new Error(reason), + type: "Sync Failed", + context: { status }, + }).catch(() => {}); +}; + export const endSyncTask = async ( worker: string, status: Enums<"task_status">, @@ -63,19 +88,11 @@ export const endSyncTask = async ( }); if (error) { console.error("endSyncTask: Error calling end_sync_task:", error); - if (showToast) { - renderToast({ - id: "discourse-embedding-error", - content: "Failed to complete discourse node embeddings sync", - intent: "danger", - timeout: 5000, - }); - } - sendErrorEmail({ - error: new Error("Failed to complete discourse node embeddings sync"), - type: "Sync Failed", - context: { status }, - }).catch(() => {}); + notifyEndSyncFailure({ + status, + showToast, + reason: `Supabase end_sync_task RPC failed: ${error.message ?? "Unknown error"}`, + }); return; } else if (showToast) { @@ -90,19 +107,14 @@ export const endSyncTask = async ( } } catch (error) { console.error("endSyncTask: Error calling end_sync_task:", error); - if (showToast) { - renderToast({ - id: "discourse-embedding-error", - content: "Failed to complete discourse node embeddings sync", - intent: "danger", - timeout: 5000, - }); - } - sendErrorEmail({ - error: new Error("Failed to complete discourse node embeddings sync"), - type: "Sync Failed", - context: { status }, - }).catch(() => {}); + notifyEndSyncFailure({ + status, + showToast, + reason: + error instanceof Error + ? `Unexpected error ending sync task: ${error.message}` + : "Unexpected non-error thrown while ending sync task", + }); } };