Skip to content

chore(platform): clean up sub-threads when parent thread is deleted#486

Merged
larryro merged 3 commits into
mainfrom
chore/73-sub-thread-cleanup
Feb 17, 2026
Merged

chore(platform): clean up sub-threads when parent thread is deleted#486
larryro merged 3 commits into
mainfrom
chore/73-sub-thread-cleanup

Conversation

@larryro

@larryro larryro commented Feb 17, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • When a chat thread is deleted (archived), any sub-threads referenced in the thread summary are now cleaned up asynchronously via a scheduled internal mutation
  • Adds parseSubThreadIds helper to extract sub-thread IDs from the thread summary JSON
  • Adds cleanupOrphanedSubThreads internal mutation that archives active sub-threads

Test plan

  • Unit tests for parseSubThreadIds covering edge cases (undefined, empty, invalid JSON, valid data)
  • Unit tests for deleteChatThread verifying sub-thread cleanup is scheduled only when sub-threads exist
  • Verify in dev that deleting a thread with sub-threads archives all sub-threads

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • Improvements
    • Enhanced chat thread deletion to automatically clean up orphaned sub-threads when a parent thread is deleted, ensuring proper archiving of related conversations and maintaining thread hierarchy consistency.

When a parent thread is archived, schedule an async cleanup that
archives its sub-threads. Sub-thread IDs are parsed from the parent's
summary JSON and the cleanup runs via ctx.scheduler.runAfter(0, ...)
to avoid blocking the deletion mutation.

Refs #73
@coderabbitai

coderabbitai Bot commented Feb 17, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

The changes implement sub-thread cleanup functionality triggered when a parent thread is deleted. A new parseSubThreadIds function extracts sub-thread identifiers from thread summary JSON data. The deleteChatThread workflow is updated to fetch the parent thread, parse any sub-thread IDs, and conditionally schedule an async cleanup mutation if sub-threads exist. A new internal mutation cleanupOrphanedSubThreads iterates through provided sub-thread IDs, fetches each sub-thread, and archives those with active status. Comprehensive unit tests cover edge cases including missing data, invalid JSON, absent sub-threads, and successful cleanup execution with verification of scheduling and mutation invocation.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

  • chore: implement sub-thread cleanup for parent thread deletion #73: This PR directly implements the code-level sub-thread cleanup mechanism (parsing subThread IDs from summaries, scheduling async cleanup, and executing the cleanupOrphanedSubThreads mutation) that addresses the issue's requirement for sub-thread cleanup on parent thread deletion.
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: implementing cleanup of sub-threads when a parent thread is deleted, which is the core functionality added across all modified files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 chore/73-sub-thread-cleanup

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@services/platform/convex/threads/delete_chat_thread.ts`:
- Around line 10-17: The code calls components.agent.threads.updateThread
unconditionally after fetching the thread with
components.agent.threads.getThread; add an explicit guard on the fetched thread
(e.g., check if thread is null/undefined) and skip or return early (or throw a
404) instead of calling updateThread when no thread exists; ensure you reference
the same threadId and preserve the existing patch { status: 'archived' }
behavior when the thread is present.

Comment thread services/platform/convex/threads/delete_chat_thread.ts
@greptile-apps

greptile-apps Bot commented Feb 17, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds sub-thread cleanup when a parent chat thread is deleted (archived). The deleteChatThread function now queries the thread's summary to extract sub-thread IDs, and if any exist, schedules an asynchronous cleanupOrphanedSubThreads internal mutation to archive them. A parseSubThreadIds helper provides defensive JSON parsing with proper error handling.

  • Adds getThread query in deleteChatThread to read the parent thread's summary before archiving
  • Introduces parseSubThreadIds to safely extract sub-thread IDs from the summary JSON (handles undefined, empty, invalid JSON, and non-string values)
  • Adds cleanupOrphanedSubThreads internal mutation that sequentially checks and archives active sub-threads
  • Sub-thread cleanup is scheduled via ctx.scheduler.runAfter(0, ...) for async execution outside the parent transaction
  • Includes comprehensive unit tests for the parsing helper and delete function behavior

Confidence Score: 4/5

  • This PR is safe to merge with minimal risk — the changes are well-structured, defensive, and the async cleanup approach avoids impacting parent thread deletion.
  • Score reflects clean implementation with defensive error handling, good test coverage of the parsing logic and deletion flow, and appropriate use of async scheduling to isolate cleanup from the main operation. Deducted one point because the cleanupOrphanedSubThreads mutation itself lacks direct unit tests, and the parent thread is archived even when getThread returns null (though this is pre-existing behavior).
  • No files require special attention, though services/platform/convex/threads/internal_mutations.ts could benefit from direct unit tests for the cleanupOrphanedSubThreads handler.

Important Files Changed

Filename Overview
services/platform/convex/threads/delete_chat_thread.ts Adds getThread query before archiving to extract sub-thread IDs from summary, then schedules async cleanup. Defensive parsing with try/catch. Archives parent even when thread not found (pre-existing behavior).
services/platform/convex/threads/internal_mutations.ts Adds cleanupOrphanedSubThreads internal mutation that iterates sub-thread IDs, checks each is active, and archives them sequentially. Includes logging of archived count.
services/platform/convex/threads/delete_chat_thread.test.ts New test file with thorough unit tests for parseSubThreadIds (7 edge cases) and deleteChatThread (4 scenarios covering archive, no sub-threads, with sub-threads, and missing thread). No tests for the cleanupOrphanedSubThreads mutation itself.

Sequence Diagram

sequenceDiagram
    participant Client
    participant deleteChatThread
    participant AgentSDK as Agent SDK (Threads)
    participant Scheduler
    participant cleanupMutation as cleanupOrphanedSubThreads

    Client->>deleteChatThread: delete(threadId)
    deleteChatThread->>AgentSDK: getThread(threadId)
    AgentSDK-->>deleteChatThread: thread (with summary)
    deleteChatThread->>AgentSDK: updateThread(archived)
    deleteChatThread->>deleteChatThread: parseSubThreadIds(summary)

    alt Sub-threads exist
        deleteChatThread->>Scheduler: runAfter(0, cleanupOrphanedSubThreads)
        Scheduler->>cleanupMutation: execute(parentThreadId, subThreadIds)
        loop For each subThreadId
            cleanupMutation->>AgentSDK: getThread(subThreadId)
            AgentSDK-->>cleanupMutation: subThread
            alt subThread is active
                cleanupMutation->>AgentSDK: updateThread(archived)
            end
        end
        cleanupMutation-->>Scheduler: { archivedCount }
    end

    deleteChatThread-->>Client: void
Loading

Last reviewed commit: cadc6b6

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

3 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment thread services/platform/convex/threads/internal_mutations.ts
@larryro larryro merged commit 5c5ad7c into main Feb 17, 2026
17 checks passed
@larryro larryro deleted the chore/73-sub-thread-cleanup branch February 17, 2026 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.

1 participant