Skip to content

Conversation

@ItzNotABug
Copy link
Member

@ItzNotABug ItzNotABug commented Nov 3, 2025

What does this PR do?

Move realtime to individual pages.

Test Plan

Manual.

Related PRs and Issues

N/A.

Have you read the Contributing Guidelines on issues?

Yes.

Summary by CodeRabbit

  • New Features

    • Added real-time synchronization for database columns and indexes; UI now automatically updates when changes occur.
  • Improvements

    • Optimized cache invalidation to prevent unnecessary refreshes when generating sample data.
    • Enhanced state management for improved consistency across the application.

@ItzNotABug ItzNotABug self-assigned this Nov 3, 2025
@appwrite
Copy link

appwrite bot commented Nov 3, 2025

Console

Project ID: 688b7bf400350cbd60e9

Sites (1)
Site Status Logs Preview QR
 console-stage
688b7cf6003b1842c9dc
Ready Ready View Logs Preview URL QR Code

Tip

Appwrite has a Discord community with over 16 000 members.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 3, 2025

Walkthrough

This pull request refactors real-time update handling and state management for database operations. It introduces a shared store isWaterfallFromFaker to track when fake data is being populated, adds real-time event listeners to multiple table-related pages (columns and indexes) that invalidate the UI on relevant events with conditional logic based on the new store, and adjusts the invalidation flow by removing a manual call in deleteColumn.svelte while making another awaited in spreadsheet.svelte. Additionally, it removes the initial endpoint/project configuration for the realtime client in non-building scenarios and eliminates unused suggestion-related exports.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Areas requiring extra attention:

  • Real-time listener initialization pattern: Verify that realtime.forProject() calls in columns/+page.svelte and indexes/+page.svelte follow consistent patterns and properly clean up listeners on component unmount
  • Invalidation logic conditional on isWaterfallFromFaker: In columns/+page.svelte, confirm that the update event only triggers invalidation when isWaterfallFromFaker is false, and validate this prevents unnecessary noise during fake data population
  • Removed invalidate call: Ensure that removing invalidate(Dependencies.TABLE) from deleteColumn.svelte is safe, as real-time listeners now handle this invalidation separately
  • Awaited invalidation: Confirm that awaiting invalidate() in spreadsheet.svelte doesn't introduce unexpected timing or race conditions
  • Store initialization and consumption: Verify that isWaterfallFromFaker is properly initialized to false and consistently used across all referencing components

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title 'Update: move realtime to specific pages' directly aligns with the primary objective of the changeset. The modifications across multiple files demonstrate a systematic refactoring to move realtime subscription logic from centralized locations to individual pages (columns, indexes), while also introducing a new store-based flag to manage state. The title accurately captures the main architectural change being implemented.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-dat-813

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte (1)

293-375: Ensure isWaterfallFromFaker is reset on early exit.

At line 293, isWaterfallFromFaker is set to true, and at line 372 it's set back to false. However, there's an early return at line 319 that exits the function without resetting the store. This could leave isWaterfallFromFaker stuck at true if column generation fails.

Apply this diff to ensure the store is always reset:

     async function createFakeData() {
         isWaterfallFromFaker.set(true);
 
         $spreadsheetLoading = true;
         $randomDataModalState.show = false;
 
         let columns = page.data.table.columns as Columns[];
         const hasAnyRelationships = columns.some((column) => isRelationship(column));
         const filteredColumns = columns.filter((col) => col.type !== 'relationship');
 
         if (!filteredColumns.length) {
             try {
                 const { startWaiting, waitPromise } = setupColumnObserver();
                 columns = await generateColumns($project, page.params.database, page.params.table);
                 startWaiting(columns.length);
                 await waitPromise;
 
                 await invalidate(Dependencies.TABLE);
                 columns = page.data.table.columns as Columns[];
 
                 trackEvent(Submit.ColumnCreate, { type: 'faker' });
             } catch (e) {
                 addNotification({
                     type: 'error',
                     message: e.message
                 });
                 $spreadsheetLoading = false;
+                isWaterfallFromFaker.set(false);
                 return;
             }
         }
 
         let rowIds = [];
         try {
             const { rows, ids } = generateFakeRecords(columns, $randomDataModalState.value);
 
             rowIds = ids;
             const tablesSDK = sdk.forProject(page.params.region, page.params.project).tablesDB;
 
             if (hasAnyRelationships) {
                 for (const batch of chunks(rows)) {
                     try {
                         await Promise.all(
                             batch.map((row) =>
                                 tablesSDK.createRow({
                                     databaseId: page.params.database,
                                     tableId: page.params.table,
                                     rowId: row.$id,
                                     data: row
                                 })
                             )
                         );
                     } catch (error) {
                         // ignore, its sample data.
                     }
                 }
             } else {
                 await tablesSDK.createRows({
                     databaseId: page.params.database,
                     tableId: page.params.table,
                     rows
                 });
             }
 
             addNotification({
                 type: 'success',
                 message: 'Sample data added successfully'
             });
 
             await invalidate(Dependencies.ROWS);
         } catch (e) {
             addNotification({
                 type: 'error',
                 message: e.message
             });
         } finally {
             // reset value to 25 default!
             $randomDataModalState.value = 25;
         }
 
         $spreadsheetLoading = false;
         isWaterfallFromFaker.set(false);
 
         spreadsheetRenderKey.set(hash(rowIds));
     }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 95528de and db465c1.

📒 Files selected for processing (7)
  • src/lib/stores/sdk.ts (0 hunks)
  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte (4 hunks)
  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/columns/+page.svelte (3 hunks)
  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/columns/deleteColumn.svelte (0 hunks)
  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/indexes/+page.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/spreadsheet.svelte (1 hunks)
  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/store.ts (1 hunks)
💤 Files with no reviewable changes (2)
  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/columns/deleteColumn.svelte
  • src/lib/stores/sdk.ts
🧰 Additional context used
🧠 Learnings (8)
📓 Common learnings
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2373
File: src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/empty.svelte:536-552
Timestamp: 2025-09-25T04:21:57.071Z
Learning: In the Appwrite console database suggestions flow, after successfully creating columns via `createColumns()`, the `await invalidate(Dependencies.TABLE)` call causes the view to be destroyed and another view (populated table view) to be rendered, automatically cleaning up component state without needing manual reset.
📚 Learning: 2025-09-25T04:21:57.071Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2373
File: src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/empty.svelte:536-552
Timestamp: 2025-09-25T04:21:57.071Z
Learning: In the Appwrite console database suggestions flow, after successfully creating columns via `createColumns()`, the `await invalidate(Dependencies.TABLE)` call causes the view to be destroyed and another view (populated table view) to be rendered, automatically cleaning up component state without needing manual reset.

Applied to files:

  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/indexes/+page.svelte
  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/store.ts
  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte
  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/spreadsheet.svelte
  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/columns/+page.svelte
📚 Learning: 2025-09-30T07:41:06.679Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2425
File: src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/empty.svelte:454-468
Timestamp: 2025-09-30T07:41:06.679Z
Learning: In `src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/empty.svelte`, the column suggestions API (console.suggestColumns) has a maximum limit of 7 columns returned, which aligns with the initial placeholder count of 7 in customColumns.

Applied to files:

  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/indexes/+page.svelte
  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte
  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/spreadsheet.svelte
  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/columns/+page.svelte
📚 Learning: 2025-10-07T14:17:11.597Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2413
File: src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/helpers/terminology.ts:28-28
Timestamp: 2025-10-07T14:17:11.597Z
Learning: In src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/helpers/terminology.ts, the empty `vectordb: {}` entry in baseTerminology is intentional. The vectordb database type is not currently used because the backend API is not finalized, and no database type returns 'vectordb' at the moment.

Applied to files:

  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/store.ts
📚 Learning: 2025-10-26T10:20:29.792Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2509
File: src/routes/(console)/project-[region]-[project]/auth/teams/+page.svelte:47-61
Timestamp: 2025-10-26T10:20:29.792Z
Learning: When deleting teams in the Appwrite Console codebase, only `Dependencies.TEAMS` needs to be invalidated. Additional invalidations for `Dependencies.TEAM` (detail route) and `Dependencies.MEMBERSHIPS` are not necessary because the deleted teams and their memberships no longer exist.

Applied to files:

  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/spreadsheet.svelte
📚 Learning: 2025-10-13T05:13:54.542Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2413
File: src/routes/(console)/project-[region]-[project]/databases/table.svelte:33-39
Timestamp: 2025-10-13T05:13:54.542Z
Learning: In Svelte 5, `import { page } from '$app/state'` provides a reactive state proxy that can be accessed directly (e.g., `page.params`), unlike the older `import { page } from '$app/stores'` which returns a readable store requiring the `$page` syntax for auto-subscription in components.

Applied to files:

  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/columns/+page.svelte
📚 Learning: 2025-10-05T09:41:40.439Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2398
File: src/routes/(console)/verify-email/+page.svelte:48-51
Timestamp: 2025-10-05T09:41:40.439Z
Learning: In SvelteKit 5, `page` imported from `$app/state` is a reactive state object (using runes), not a store. It should be accessed as `page.data` without the `$` prefix, unlike the store-based `$page` from `$app/stores` in earlier versions.

Applied to files:

  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/columns/+page.svelte
📚 Learning: 2025-10-13T05:16:07.656Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2413
File: src/routes/(console)/project-[region]-[project]/databases/database-[database]/header.svelte:54-58
Timestamp: 2025-10-13T05:16:07.656Z
Learning: In SvelteKit apps, shared layout components (like headers) that use `$derived(page.data.*)` should use optional chaining when accessing properties that may not be present on all routes. During page transitions, reactive statements can briefly evaluate with different page.data structures, so optional chaining prevents runtime errors when navigating between routes with different data shapes (e.g., between `/databases` and `/databases/database-[database]`).

Applied to files:

  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/columns/+page.svelte
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: e2e
🔇 Additional comments (7)
src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/indexes/+page.svelte (1)

40-42: LGTM!

The imports for realtime, invalidate, and Dependencies are correctly added to support the new real-time event listener.

src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/spreadsheet.svelte (1)

478-478: LGTM!

Awaiting invalidation ensures that the table data refresh completes before resetting the column sheet options at line 480. This aligns with the centralized real-time invalidation approach introduced in this PR.

src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/store.ts (1)

31-35: LGTM!

The new isWaterfallFromFaker store is well-documented and provides a clean mechanism to coordinate real-time invalidation behavior across multiple components during fake data generation.

src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/columns/+page.svelte (2)

26-26: LGTM!

The imports correctly bring in the shared isWaterfallFromFaker store and the necessary dependencies for real-time invalidation.

Also applies to: 59-61


144-157: LGTM!

The real-time listener properly:

  • Returns a cleanup function from onMount
  • Always invalidates on column delete events
  • Gates update event invalidation when $isWaterfallFromFaker is true to reduce API noise during fake data generation
  • Awaits invalidation to ensure completion

This implementation aligns well with the PR objective of moving realtime to specific pages.

src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte (2)

39-39: LGTM!

Importing the shared isWaterfallFromFaker store enables coordination of real-time invalidation behavior across table-related components.


84-94: LGTM!

The real-time listener correctly gates columnCreationHandler invocation to only when $isWaterfallFromFaker is true, ensuring the handler only tracks column creation during fake data generation.

@ItzNotABug ItzNotABug merged commit c5fd02a into main Nov 3, 2025
4 checks passed
@ItzNotABug ItzNotABug deleted the fix-dat-813 branch November 3, 2025 13:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants