fix auto-index race conditions and orphaned toasts

This commit is contained in:
CREDO23 2026-03-10 17:10:24 +02:00
parent 20ca49087f
commit dfb1c6534d
2 changed files with 63 additions and 42 deletions

View file

@ -241,25 +241,27 @@ export const COMPOSIO_TOOLKITS = [
},
] as const;
// Per-connector defaults for auto-indexing after OAuth (days back, days forward, periodic frequency in minutes)
export const AUTO_INDEX_DEFAULTS: Record<string, { daysBack: number; daysForward: number; frequencyMinutes: number }> = {
// Messaging — high volume, recent messages matter most
[EnumConnectorName.GOOGLE_GMAIL_CONNECTOR]: { daysBack: 30, daysForward: 0, frequencyMinutes: 1440 },
[EnumConnectorName.COMPOSIO_GMAIL_CONNECTOR]: { daysBack: 30, daysForward: 0, frequencyMinutes: 1440 },
[EnumConnectorName.SLACK_CONNECTOR]: { daysBack: 30, daysForward: 0, frequencyMinutes: 1440 },
[EnumConnectorName.DISCORD_CONNECTOR]: { daysBack: 30, daysForward: 0, frequencyMinutes: 1440 },
[EnumConnectorName.TEAMS_CONNECTOR]: { daysBack: 30, daysForward: 0, frequencyMinutes: 1440 },
// Calendar — past context + upcoming events
[EnumConnectorName.GOOGLE_CALENDAR_CONNECTOR]: { daysBack: 90, daysForward: 90, frequencyMinutes: 1440 },
[EnumConnectorName.COMPOSIO_GOOGLE_CALENDAR_CONNECTOR]: { daysBack: 90, daysForward: 90, frequencyMinutes: 1440 },
// Project management — medium-term relevance
[EnumConnectorName.LINEAR_CONNECTOR]: { daysBack: 90, daysForward: 0, frequencyMinutes: 1440 },
[EnumConnectorName.JIRA_CONNECTOR]: { daysBack: 90, daysForward: 0, frequencyMinutes: 1440 },
[EnumConnectorName.CLICKUP_CONNECTOR]: { daysBack: 90, daysForward: 0, frequencyMinutes: 1440 },
// Knowledge bases — evergreen content
[EnumConnectorName.NOTION_CONNECTOR]: { daysBack: 365, daysForward: 0, frequencyMinutes: 1440 },
[EnumConnectorName.CONFLUENCE_CONNECTOR]: { daysBack: 365, daysForward: 0, frequencyMinutes: 1440 },
[EnumConnectorName.AIRTABLE_CONNECTOR]: { daysBack: 365, daysForward: 0, frequencyMinutes: 1440 },
export interface AutoIndexConfig {
daysBack: number;
daysForward: number;
frequencyMinutes: number;
syncDescription: string;
}
export const AUTO_INDEX_DEFAULTS: Record<string, AutoIndexConfig> = {
[EnumConnectorName.GOOGLE_GMAIL_CONNECTOR]: { daysBack: 30, daysForward: 0, frequencyMinutes: 1440, syncDescription: "Syncing your last 30 days of emails." },
[EnumConnectorName.COMPOSIO_GMAIL_CONNECTOR]: { daysBack: 30, daysForward: 0, frequencyMinutes: 1440, syncDescription: "Syncing your last 30 days of emails." },
[EnumConnectorName.SLACK_CONNECTOR]: { daysBack: 30, daysForward: 0, frequencyMinutes: 1440, syncDescription: "Syncing your last 30 days of messages." },
[EnumConnectorName.DISCORD_CONNECTOR]: { daysBack: 30, daysForward: 0, frequencyMinutes: 1440, syncDescription: "Syncing your last 30 days of messages." },
[EnumConnectorName.TEAMS_CONNECTOR]: { daysBack: 30, daysForward: 0, frequencyMinutes: 1440, syncDescription: "Syncing your last 30 days of messages." },
[EnumConnectorName.GOOGLE_CALENDAR_CONNECTOR]: { daysBack: 90, daysForward: 90, frequencyMinutes: 1440, syncDescription: "Syncing 90 days of past and upcoming events." },
[EnumConnectorName.COMPOSIO_GOOGLE_CALENDAR_CONNECTOR]: { daysBack: 90, daysForward: 90, frequencyMinutes: 1440, syncDescription: "Syncing 90 days of past and upcoming events." },
[EnumConnectorName.LINEAR_CONNECTOR]: { daysBack: 90, daysForward: 0, frequencyMinutes: 1440, syncDescription: "Syncing your last 90 days of issues." },
[EnumConnectorName.JIRA_CONNECTOR]: { daysBack: 90, daysForward: 0, frequencyMinutes: 1440, syncDescription: "Syncing your last 90 days of issues." },
[EnumConnectorName.CLICKUP_CONNECTOR]: { daysBack: 90, daysForward: 0, frequencyMinutes: 1440, syncDescription: "Syncing your last 90 days of tasks." },
[EnumConnectorName.NOTION_CONNECTOR]: { daysBack: 365, daysForward: 0, frequencyMinutes: 1440, syncDescription: "Syncing your pages." },
[EnumConnectorName.CONFLUENCE_CONNECTOR]: { daysBack: 365, daysForward: 0, frequencyMinutes: 1440, syncDescription: "Syncing your documentation." },
[EnumConnectorName.AIRTABLE_CONNECTOR]: { daysBack: 365, daysForward: 0, frequencyMinutes: 1440, syncDescription: "Syncing your bases." },
};
export const AUTO_INDEX_CONNECTOR_TYPES = new Set<string>(Object.keys(AUTO_INDEX_DEFAULTS));

View file

@ -138,7 +138,9 @@ export const useConnectorDialog = () => {
const endDate = new Date(now);
endDate.setDate(endDate.getDate() + (defaults?.daysForward ?? 0));
setIsOpen(true);
const toastId = "auto-index";
toast.loading(`Setting up ${connectorTitle}...`, { id: toastId });
try {
await updateConnector({
id: connector.id,
@ -165,32 +167,24 @@ export const useConnectorDialog = () => {
);
toast.success(`${connectorTitle} connected!`, {
description: "Syncing started. Your data will be available shortly.",
id: toastId,
description: defaults?.syncDescription ?? "Syncing started.",
});
} catch (error) {
console.error("Auto-index failed:", error);
toast.success(`${connectorTitle} connected!`, {
description:
"Connected successfully, but syncing could not start. You can start it from settings.",
toast.error(`${connectorTitle} connected, but sync failed`, {
id: toastId,
description: "You can start syncing from settings.",
});
} finally {
queryClient.invalidateQueries({
queryKey: cacheKeys.logs.summary(Number(searchSpaceId)),
});
await refetchAllConnectors();
isAutoIndexingRef.current = false;
}
const url = new URL(window.location.href);
url.searchParams.delete("success");
url.searchParams.delete("connector");
url.searchParams.delete("connectorId");
url.searchParams.delete("view");
url.searchParams.delete("modal");
url.searchParams.delete("tab");
router.replace(url.pathname + url.search, { scroll: false });
queryClient.invalidateQueries({
queryKey: cacheKeys.logs.summary(Number(searchSpaceId)),
});
await refetchAllConnectors();
isAutoIndexingRef.current = false;
},
[searchSpaceId, indexConnector, updateConnector, refetchAllConnectors, setIsOpen, router]
[searchSpaceId, indexConnector, updateConnector, refetchAllConnectors]
);
// Synchronize state with URL query params
@ -410,8 +404,29 @@ export const useConnectorDialog = () => {
}
if (params.success === "true" && searchSpaceId && params.modal === "connectors") {
// For auto-index connectors: close modal and show loading toast before refetch
const earlyConnector = params.connector
? OAUTH_CONNECTORS.find((c) => c.id === params.connector) ||
COMPOSIO_CONNECTORS.find((c) => c.id === params.connector)
: null;
if (earlyConnector && AUTO_INDEX_CONNECTOR_TYPES.has(earlyConnector.connectorType)) {
toast.loading(`Setting up ${earlyConnector.title}...`, { id: "auto-index" });
const url = new URL(window.location.href);
url.searchParams.delete("success");
url.searchParams.delete("connector");
url.searchParams.delete("connectorId");
url.searchParams.delete("view");
url.searchParams.delete("modal");
url.searchParams.delete("tab");
router.replace(url.pathname + url.search, { scroll: false });
}
refetchAllConnectors().then(async (result) => {
if (!result.data) return;
if (!result.data) {
toast.dismiss("auto-index");
return;
}
let newConnector: SearchSourceConnector | undefined;
let oauthConnector:
@ -466,6 +481,7 @@ export const useConnectorDialog = () => {
oauthConnector.connectorType
);
} else {
toast.dismiss("auto-index");
const config = validateIndexingConfigState({
connectorType: oauthConnector.connectorType,
connectorId: newConnector.id,
@ -483,8 +499,11 @@ export const useConnectorDialog = () => {
}
} else {
console.warn("Invalid connector data after OAuth:", connectorValidation.error);
toast.dismiss("auto-index");
toast.error("Failed to validate connector data");
}
} else {
toast.dismiss("auto-index");
}
});
}
@ -492,7 +511,7 @@ export const useConnectorDialog = () => {
// Invalid query params - log but don't crash
console.warn("Invalid connector popup query params in OAuth success handler:", error);
}
}, [searchParams, searchSpaceId, refetchAllConnectors, setIsOpen, handleAutoIndex]);
}, [searchParams, searchSpaceId, refetchAllConnectors, setIsOpen, handleAutoIndex, router]);
// Handle OAuth connection
const handleConnectOAuth = useCallback(