From 3b172e79093a6a4fc17f6b48971287892567302a Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 2 Dec 2025 17:47:04 +0530 Subject: [PATCH] add: column waiting logic on ai suggestions as well. --- .../(observer)/columnObserver.ts | 65 +++++++++++++++++++ .../(suggestions)/empty.svelte | 27 +++++++- .../table-[table]/+layout.svelte | 64 ++++-------------- 3 files changed, 101 insertions(+), 55 deletions(-) create mode 100644 src/routes/(console)/project-[region]-[project]/databases/database-[database]/(observer)/columnObserver.ts diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(observer)/columnObserver.ts b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(observer)/columnObserver.ts new file mode 100644 index 000000000..28ced29eb --- /dev/null +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(observer)/columnObserver.ts @@ -0,0 +1,65 @@ +import type { Columns } from '../table-[table]/store'; +import type { RealtimeResponse } from '$lib/stores/sdk'; + +export function setupColumnObserver() { + let expectedCount = 0; + let resolvePromise: () => void; + let timeout: ReturnType; + let isActive = true; + + const availableColumns = new Set(); + const waitPromise = new Promise((resolve) => (resolvePromise = resolve)); + + const columnCreationHandler = (response: RealtimeResponse) => { + if (!isActive) return; + + const { events, payload } = response; + + if ( + events.includes('databases.*.tables.*.columns.*.create') || + events.includes('databases.*.tables.*.columns.*.update') + ) { + const asColumn = payload as Columns; + const columnId = asColumn.key; + const status = asColumn.status; + + if (status === 'available') { + availableColumns.add(columnId); + + if (expectedCount > 0 && availableColumns.size >= expectedCount) { + clearTimeout(timeout); + cleanup(); + resolvePromise(); + } + } + } + }; + + const cleanup = () => { + isActive = false; + if (timeout) clearTimeout(timeout); + }; + + // return function to start waiting! + const startWaiting = (count: number) => { + expectedCount = count; + + timeout = setTimeout(() => { + cleanup(); + resolvePromise(); + }, 10000); + + if (availableColumns.size >= expectedCount) { + clearTimeout(timeout); + cleanup(); + resolvePromise(); + } + }; + + return { + cleanup, + waitPromise, + startWaiting, + columnCreationHandler + }; +} diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/empty.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/empty.svelte index 22839e48a..00347261f 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/empty.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/empty.svelte @@ -19,8 +19,9 @@ import { preferences } from '$lib/stores/preferences'; import SpreadsheetContainer from '../table-[table]/layout/spreadsheet.svelte'; import { onDestroy, onMount, tick } from 'svelte'; - import { sdk } from '$lib/stores/sdk'; + import { sdk, realtime, type RealtimeResponse } from '$lib/stores/sdk'; import { page } from '$app/state'; + import { setupColumnObserver } from '../(observer)/columnObserver'; import { type ColumnInput, mapSuggestedColumns, @@ -125,6 +126,7 @@ // let tooltipTopPosition = $state(50); let triggerColumnId = $state(null); let hoveredColumnId = $state(null); + let columnCreationHandler: ((response: RealtimeResponse) => void) | null = null; // for deleting a column + undo let undoTimer: ReturnType | null = $state(null); @@ -585,7 +587,7 @@ ($isSmallViewport ? 14 : 17) + (!$expandTabs ? 2 : 0) - userDataRows.length ); - onMount(async () => { + onMount(() => { columnsOrder.set(preferences.getColumnOrder(tableId)); columnsWidth.set(preferences.getColumnWidths(tableId)); @@ -595,7 +597,13 @@ } requestAnimationFrame(recalcAll); - await suggestColumns(); + suggestColumns(); + + return realtime.forProject(page.params.region, ['project', 'console'], (response) => { + if (response.events.includes('databases.*.tables.*.columns.*')) { + columnCreationHandler?.(response); + } + }); }); function resetSuggestionsStore(fullReset: boolean = true) { @@ -968,6 +976,14 @@ } try { + const { + startWaiting, + waitPromise, + columnCreationHandler: handler + } = setupColumnObserver(); + + columnCreationHandler = handler; + const results = []; for (const column of customColumns) { @@ -1066,6 +1082,9 @@ results.push(columnResult); } + startWaiting(customColumns.length); + await waitPromise; + await invalidate(Dependencies.TABLE); addNotification({ @@ -1087,6 +1106,8 @@ message: error.message }); creatingColumns = false; + } finally { + columnCreationHandler = null; } } diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte index bc4f7f186..63d3c23f4 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte @@ -73,9 +73,10 @@ import { Submit, trackEvent } from '$lib/actions/analytics'; import { isTabletViewport } from '$lib/stores/viewport'; + import { showColumnsSuggestionsModal } from '../(suggestions)'; import IndexesSuggestions from '../(suggestions)/indexes.svelte'; import ColumnsSuggestions from '../(suggestions)/columns.svelte'; - import { showColumnsSuggestionsModal } from '../(suggestions)'; + import { setupColumnObserver } from '../(observer)/columnObserver'; let editRow: EditRow; let editRelatedRow: EditRelatedRow; @@ -276,56 +277,6 @@ indexes: 700 }); - function setupColumnObserver() { - let expectedCount = 0; - let resolvePromise: () => void; - let timeout: ReturnType; - - const availableColumns = new Set(); - const waitPromise = new Promise((resolve) => (resolvePromise = resolve)); - - columnCreationHandler = (response: RealtimeResponse) => { - const { events, payload } = response; - - if ( - events.includes('databases.*.tables.*.columns.*.create') || - events.includes('databases.*.tables.*.columns.*.update') - ) { - const asColumn = payload as Columns; - const columnId = asColumn.key; - const status = asColumn.status; - - if (status === 'available') { - availableColumns.add(columnId); - - if (expectedCount > 0 && availableColumns.size >= expectedCount) { - clearTimeout(timeout); - columnCreationHandler = null; - resolvePromise(); - } - } - } - }; - - // return function to start waiting! - const startWaiting = (count: number) => { - expectedCount = count; - - timeout = setTimeout(() => { - columnCreationHandler = null; - resolvePromise(); - }, 10000); - - if (availableColumns.size >= expectedCount) { - clearTimeout(timeout); - columnCreationHandler = null; - resolvePromise(); - } - }; - - return { startWaiting, waitPromise }; - } - async function createFakeData() { isWaterfallFromFaker.set(true); @@ -338,7 +289,14 @@ if (!filteredColumns.length) { try { - const { startWaiting, waitPromise } = setupColumnObserver(); + const { + startWaiting, + waitPromise, + columnCreationHandler: handler + } = setupColumnObserver(); + + columnCreationHandler = handler; + columns = await generateColumns($project, page.params.database, page.params.table); startWaiting(columns.length); await waitPromise; @@ -354,6 +312,8 @@ }); $spreadsheetLoading = false; return; + } finally { + columnCreationHandler = null; } }