Skip to content

Conversation

@sid597
Copy link
Collaborator

@sid597 sid597 commented Aug 3, 2025

Summary by CodeRabbit

  • Refactor

    • Improved orphaned node cleanup by switching from external API calls to direct database queries, resulting in more efficient and reliable operations.
  • Chores

    • Removed obsolete API endpoints related to discourse node retrieval and deletion.

@linear
Copy link

linear bot commented Aug 3, 2025

@supabase
Copy link

supabase bot commented Aug 3, 2025

This pull request has been ignored for the connected project zytfjzqyijgagqxrzbmz because there are no changes detected in packages/database/supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@sid597
Copy link
Collaborator Author

sid597 commented Aug 3, 2025

@coderabbitai full review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 3, 2025

✅ Actions performed

Full review triggered.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 3, 2025

📝 Walkthrough

Walkthrough

This change removes two API route files responsible for fetching and deleting discourse nodes via HTTP endpoints and refactors the cleanupOrphanedNodes.ts utility to interact directly with Supabase using the client library. The utility now queries and deletes nodes without relying on external REST API calls, updating function signatures and error handling accordingly.

Changes

Cohort / File(s) Change Summary
Refactor: Direct Supabase Client Usage in Cleanup Utility
apps/roam/src/utils/cleanupOrphanedNodes.ts
Refactored to replace REST API calls with direct Supabase client queries for fetching and deleting nodes. Updated function signatures to accept spaceId and SupabaseClient, improved error handling, and streamlined control flow.
Removal: Discourse Nodes API Endpoints
apps/website/app/api/supabase/delete-discourse-nodes/route.ts, apps/website/app/api/supabase/get-all-discourse-nodes/route.ts
Deleted API route files that previously handled POST requests for deleting and fetching discourse nodes from Supabase, removing related request/response types and handlers.

Sequence Diagram(s)

sequenceDiagram
    participant RoamCleanup as cleanupOrphanedNodes
    participant Supabase as SupabaseClient

    RoamCleanup->>Supabase: getAllNodesFromSupabase(spaceId)
    Supabase-->>RoamCleanup: Returns all node UIDs

    RoamCleanup->>RoamCleanup: Determine orphaned node UIDs

    RoamCleanup->>Supabase: deleteNodesFromSupabase(orphanedUIDs, spaceId)
    Supabase-->>RoamCleanup: Deletes nodes and related data
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15 minutes

Possibly related PRs

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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: 0

🧹 Nitpick comments (2)
apps/roam/src/utils/cleanupOrphanedNodes.ts (2)

4-31: Clarify function purpose and naming

The function name getAllNodesFromSupabase suggests retrieving all nodes, but it specifically queries concepts where schema_id is not null. This appears to fetch concept instances rather than all discourse nodes. Consider renaming to better reflect its purpose, such as getConceptInstancesFromSupabase or documenting why only concepts with schemas are relevant for orphan cleanup.


53-97: Consider the implications of partial deletion on errors

The function performs multiple delete operations without transaction support. If an error occurs after deleting concepts but before deleting content, it could leave orphaned content records. While I understand Supabase lacks transaction support (per retrieved learnings), consider documenting this limitation or implementing a retry mechanism for failed deletions.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 71ae29f and 501a740.

📒 Files selected for processing (3)
  • apps/roam/src/utils/cleanupOrphanedNodes.ts (2 hunks)
  • apps/website/app/api/supabase/delete-discourse-nodes/route.ts (0 hunks)
  • apps/website/app/api/supabase/get-all-discourse-nodes/route.ts (0 hunks)
💤 Files with no reviewable changes (2)
  • apps/website/app/api/supabase/get-all-discourse-nodes/route.ts
  • apps/website/app/api/supabase/delete-discourse-nodes/route.ts
🧰 Additional context used
🧠 Learnings (13)
📓 Common learnings
Learnt from: maparent
PR: DiscourseGraphs/discourse-graph#0
File: :0-0
Timestamp: 2025-06-07T02:56:57.093Z
Learning: In the discourse-graph project's upsert_content function, null creator_id values are tolerated as an acceptable trade-off, even though they may be annoying, rather than failing the entire operation.
Learnt from: sid597
PR: DiscourseGraphs/discourse-graph#232
File: apps/roam/src/utils/getAllDiscourseNodesSince.ts:18-31
Timestamp: 2025-06-22T10:40:52.752Z
Learning: In apps/roam/src/utils/getAllDiscourseNodesSince.ts, the user confirmed that querying for `?title` with `:node/title` and mapping it to the `text` field in the DiscourseGraphContent type is the correct implementation for retrieving discourse node content from Roam Research, despite it appearing to query page titles rather than block text content.
Learnt from: CR
PR: DiscourseGraphs/discourse-graph#0
File: .cursor/rules/api.mdc:0-0
Timestamp: 2025-07-19T22:33:54.521Z
Learning: You are working on the api routes for Discourse Graph which uses NextJS app router.
Learnt from: maparent
PR: DiscourseGraphs/discourse-graph#241
File: packages/database/tsconfig.json:3-7
Timestamp: 2025-06-25T18:03:52.669Z
Learning: The packages/database directory in the discourse-graph repository has a unique structure as a database schema/migration package. It contains doc/, scripts/, supabase/ directories and TypeScript files at the root level, but no typical src/, test/, dist/, or node_modules directories. The current tsconfig.json with "include": ["."] and "exclude": ["supabase"] is appropriate for this structure.
Learnt from: sid597
PR: DiscourseGraphs/discourse-graph#232
File: apps/roam/src/utils/getAllDiscourseNodesSince.ts:15-16
Timestamp: 2025-06-22T10:40:21.679Z
Learning: In the getAllDiscourseNodesSince function in apps/roam/src/utils/getAllDiscourseNodesSince.ts, date validation is performed before the function is called, so additional date validation within the function is not needed.
Learnt from: maparent
PR: DiscourseGraphs/discourse-graph#165
File: packages/database/supabase/migrations/20250513173724_content_concept_key.sql:37-60
Timestamp: 2025-05-22T23:50:23.771Z
Learning: For the discourse-graph project, database schema management focuses on the final state in the supabase/schemas directory, not on the individual migration files. When reviewing database changes, consider only the schema definitions in this directory, not potential duplications or conflicts across migration files.
Learnt from: maparent
PR: DiscourseGraphs/discourse-graph#182
File: apps/website/app/utils/supabase/dbUtils.ts:22-28
Timestamp: 2025-05-30T14:49:24.016Z
Learning: In apps/website/app/utils/supabase/dbUtils.ts, expanding the KNOWN_EMBEDDINGS and DEFAULT_DIMENSIONS mappings to support additional embedding models requires corresponding database model changes (creating new embedding tables), which should be scoped as separate work from API route implementations.
Learnt from: maparent
PR: DiscourseGraphs/discourse-graph#220
File: apps/roam/src/utils/conceptConversion.ts:42-56
Timestamp: 2025-06-17T23:37:45.289Z
Learning: In the DiscourseNode interface from apps/roam/src/utils/getDiscourseNodes.ts, the field `type` serves as the unique identifier field, not a type classification field. The interface has no `uid` or `id` field, making `node.type` the correct field to use for UID-related operations.
Learnt from: maparent
PR: DiscourseGraphs/discourse-graph#182
File: apps/website/app/api/supabase/rpc/search-content/route.ts:53-56
Timestamp: 2025-05-30T14:37:30.215Z
Learning: The search-content route (apps/website/app/api/supabase/rpc/search-content/route.ts) is intentionally designed to be platform-agnostic rather than Roam-specific. The generic "Platform" terminology (like subsetPlatformIds) is used because the route will support multiple platforms in the near future, not just Roam.
Learnt from: maparent
PR: DiscourseGraphs/discourse-graph#291
File: packages/database/supabase/functions/create-space/index.ts:0-0
Timestamp: 2025-07-21T14:22:20.752Z
Learning: In the discourse-graph codebase, types.gen.ts is not accessible from Supabase edge functions, requiring duplication of types and utilities when needed in the edge function environment at packages/database/supabase/functions/.
Learnt from: maparent
PR: DiscourseGraphs/discourse-graph#220
File: apps/roam/src/utils/conceptConversion.ts:42-56
Timestamp: 2025-06-17T23:37:45.289Z
Learning: In the DiscourseNode interface from apps/roam/src/utils/getDiscourseNodes.ts, the field `node.type` serves as the UID field rather than having a conventional `node.uid` field. This is an unusual naming convention where the type field actually contains the unique identifier.
📚 Learning: the supabase client does not offer transaction support, so idempotent upserts with proper conflict r...
Learnt from: maparent
PR: DiscourseGraphs/discourse-graph#272
File: packages/ui/src/lib/supabase/contextFunctions.ts:50-111
Timestamp: 2025-07-08T14:48:38.048Z
Learning: The Supabase client does not offer transaction support, so idempotent upserts with proper conflict resolution (using onConflict with ignoreDuplicates: false) are the preferred approach for multi-step database operations in packages/ui/src/lib/supabase/contextFunctions.ts. This pattern prevents orphaned records when retrying operations.

Applied to files:

  • apps/roam/src/utils/cleanupOrphanedNodes.ts
📚 Learning: in apps/roam/src/utils/getalldiscoursenodessince.ts, the user confirmed that querying for `?title` w...
Learnt from: sid597
PR: DiscourseGraphs/discourse-graph#232
File: apps/roam/src/utils/getAllDiscourseNodesSince.ts:18-31
Timestamp: 2025-06-22T10:40:52.752Z
Learning: In apps/roam/src/utils/getAllDiscourseNodesSince.ts, the user confirmed that querying for `?title` with `:node/title` and mapping it to the `text` field in the DiscourseGraphContent type is the correct implementation for retrieving discourse node content from Roam Research, despite it appearing to query page titles rather than block text content.

Applied to files:

  • apps/roam/src/utils/cleanupOrphanedNodes.ts
📚 Learning: in the getalldiscoursenodessince function in apps/roam/src/utils/getalldiscoursenodessince.ts, date ...
Learnt from: sid597
PR: DiscourseGraphs/discourse-graph#232
File: apps/roam/src/utils/getAllDiscourseNodesSince.ts:15-16
Timestamp: 2025-06-22T10:40:21.679Z
Learning: In the getAllDiscourseNodesSince function in apps/roam/src/utils/getAllDiscourseNodesSince.ts, date validation is performed before the function is called, so additional date validation within the function is not needed.

Applied to files:

  • apps/roam/src/utils/cleanupOrphanedNodes.ts
📚 Learning: the search-content route (apps/website/app/api/supabase/rpc/search-content/route.ts) is intentionall...
Learnt from: maparent
PR: DiscourseGraphs/discourse-graph#182
File: apps/website/app/api/supabase/rpc/search-content/route.ts:53-56
Timestamp: 2025-05-30T14:37:30.215Z
Learning: The search-content route (apps/website/app/api/supabase/rpc/search-content/route.ts) is intentionally designed to be platform-agnostic rather than Roam-specific. The generic "Platform" terminology (like subsetPlatformIds) is used because the route will support multiple platforms in the near future, not just Roam.

Applied to files:

  • apps/roam/src/utils/cleanupOrphanedNodes.ts
📚 Learning: in the discoursenode interface from apps/roam/src/utils/getdiscoursenodes.ts, the field `type` serve...
Learnt from: maparent
PR: DiscourseGraphs/discourse-graph#220
File: apps/roam/src/utils/conceptConversion.ts:42-56
Timestamp: 2025-06-17T23:37:45.289Z
Learning: In the DiscourseNode interface from apps/roam/src/utils/getDiscourseNodes.ts, the field `type` serves as the unique identifier field, not a type classification field. The interface has no `uid` or `id` field, making `node.type` the correct field to use for UID-related operations.

Applied to files:

  • apps/roam/src/utils/cleanupOrphanedNodes.ts
📚 Learning: applies to apps/roam/**/*.{js,jsx,ts,tsx} : use the roamalphaapi documentation from https://roamrese...
Learnt from: CR
PR: DiscourseGraphs/discourse-graph#0
File: .cursor/rules/roam.mdc:0-0
Timestamp: 2025-07-19T22:34:23.619Z
Learning: Applies to apps/roam/**/*.{js,jsx,ts,tsx} : Use the roamAlphaApi documentation from https://roamresearch.com/#/app/developer-documentation/page/tIaOPdXCj when working with the Roam API

Applied to files:

  • apps/roam/src/utils/cleanupOrphanedNodes.ts
📚 Learning: in apps/website/app/utils/supabase/dbutils.ts, expanding the known_embeddings and default_dimensions...
Learnt from: maparent
PR: DiscourseGraphs/discourse-graph#182
File: apps/website/app/utils/supabase/dbUtils.ts:22-28
Timestamp: 2025-05-30T14:49:24.016Z
Learning: In apps/website/app/utils/supabase/dbUtils.ts, expanding the KNOWN_EMBEDDINGS and DEFAULT_DIMENSIONS mappings to support additional embedding models requires corresponding database model changes (creating new embedding tables), which should be scoped as separate work from API route implementations.

Applied to files:

  • apps/roam/src/utils/cleanupOrphanedNodes.ts
📚 Learning: applies to apps/roam/**/*.{js,jsx,ts,tsx} : use roam depot/extension api documentation from https://...
Learnt from: CR
PR: DiscourseGraphs/discourse-graph#0
File: .cursor/rules/roam.mdc:0-0
Timestamp: 2025-07-19T22:34:23.619Z
Learning: Applies to apps/roam/**/*.{js,jsx,ts,tsx} : Use Roam Depot/Extension API documentation from https://roamresearch.com/#/app/developer-documentation/page/y31lhjIqU when working with the Roam Extension API

Applied to files:

  • apps/roam/src/utils/cleanupOrphanedNodes.ts
📚 Learning: in the discourse-graph codebase, types.gen.ts is not accessible from supabase edge functions, requir...
Learnt from: maparent
PR: DiscourseGraphs/discourse-graph#291
File: packages/database/supabase/functions/create-space/index.ts:0-0
Timestamp: 2025-07-21T14:22:20.752Z
Learning: In the discourse-graph codebase, types.gen.ts is not accessible from Supabase edge functions, requiring duplication of types and utilities when needed in the edge function environment at packages/database/supabase/functions/.

Applied to files:

  • apps/roam/src/utils/cleanupOrphanedNodes.ts
📚 Learning: in the discoursenode interface from apps/roam/src/utils/getdiscoursenodes.ts, the field `node.type` ...
Learnt from: maparent
PR: DiscourseGraphs/discourse-graph#220
File: apps/roam/src/utils/conceptConversion.ts:42-56
Timestamp: 2025-06-17T23:37:45.289Z
Learning: In the DiscourseNode interface from apps/roam/src/utils/getDiscourseNodes.ts, the field `node.type` serves as the UID field rather than having a conventional `node.uid` field. This is an unusual naming convention where the type field actually contains the unique identifier.

Applied to files:

  • apps/roam/src/utils/cleanupOrphanedNodes.ts
📚 Learning: in the `match_embeddings_for_subset_nodes` sql function in packages/database/supabase/schemas/embedd...
Learnt from: maparent
PR: DiscourseGraphs/discourse-graph#165
File: packages/database/supabase/schemas/embedding.sql:66-95
Timestamp: 2025-05-20T14:04:19.632Z
Learning: In the `match_embeddings_for_subset_nodes` SQL function in packages/database/supabase/schemas/embedding.sql, the number of results is implicitly limited by the length of the input array parameter `p_subset_roam_uids` since the function filters content using `WHERE c.source_local_id = ANY(p_subset_roam_uids)`.

Applied to files:

  • apps/roam/src/utils/cleanupOrphanedNodes.ts
📚 Learning: the packages/database directory in the discourse-graph repository has a unique structure as a databa...
Learnt from: maparent
PR: DiscourseGraphs/discourse-graph#241
File: packages/database/tsconfig.json:3-7
Timestamp: 2025-06-25T18:03:52.669Z
Learning: The packages/database directory in the discourse-graph repository has a unique structure as a database schema/migration package. It contains doc/, scripts/, supabase/ directories and TypeScript files at the root level, but no typical src/, test/, dist/, or node_modules directories. The current tsconfig.json with "include": ["."] and "exclude": ["supabase"] is appropriate for this structure.

Applied to files:

  • apps/roam/src/utils/cleanupOrphanedNodes.ts
🔇 Additional comments (3)
apps/roam/src/utils/cleanupOrphanedNodes.ts (3)

33-51: LGTM!

The Roam query correctly identifies UIDs that no longer exist in the graph using a negative existence check. Good error handling.


99-121: Well-structured cleanup implementation

The function properly handles the cleanup flow with appropriate error checking and early returns for optimization. Good separation of concerns by passing the Supabase client and spaceId to helper functions.


1-2: Good refactoring to eliminate API dependencies

The refactoring to use direct Supabase client queries instead of external REST API endpoints improves efficiency and reduces network overhead. This architectural change appropriately consolidates discourse node management within the Roam app context.

@sid597 sid597 requested review from maparent and mdroidian August 3, 2025 19:01
Copy link
Collaborator

@maparent maparent left a comment

Choose a reason for hiding this comment

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

ok. Curious about why only removing instances and not schemas. Otherwise lgtm.

@maparent
Copy link
Collaborator

maparent commented Aug 4, 2025

One of my comments fell outside the review because I'm still learning how GitHub does reviews...

@sid597 sid597 merged commit a04e81e into main Aug 8, 2025
5 checks passed
@github-project-automation github-project-automation bot moved this to Done in General Aug 8, 2025
@sid597 sid597 deleted the eng-512-update-node-upsertdelete-to-include-concepts branch August 8, 2025 06:27
@sid597
Copy link
Collaborator Author

sid597 commented Aug 8, 2025

cc @mdroidian I merged this pr without checking that you haven't reviewed it, I thought only maparent is going to review. I can revert the merge

@sid597
Copy link
Collaborator Author

sid597 commented Aug 8, 2025

cc @mdroidian I merged this pr without checking that you have'nt reviewed it, I thought only maparent is going to review. I can revert the merge

@mdroidian
Copy link
Contributor

cc @mdroidian I merged this pr without checking that you have'nt reviewed it, I thought only maparent is going to review. I can revert the merge

All good

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

No open projects
Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants