Skip to content

feat(server): impl doc gc - #15282

Merged
darkskygit merged 3 commits into
canaryfrom
darksky/impl-doc-gc
Jul 20, 2026
Merged

feat(server): impl doc gc#15282
darkskygit merged 3 commits into
canaryfrom
darksky/impl-doc-gc

Conversation

@darkskygit

@darkskygit darkskygit commented Jul 19, 2026

Copy link
Copy Markdown
Member

PR Dependency Tree

This tree was auto-generated by Charcoal

Summary by CodeRabbit

  • New Features
    • Added automated document cleanup that marks missing workspace documents, deletes stored data, and recovers cleanly if the document reappears.
    • Introduced effect-based follow-up cleanup for search indexing, Copilot embeddings, and comment attachment objects, including acknowledgements to drive progress.
  • Bug Fixes
    • Linked reference rendering now remains stable after referenced documents are deleted (references become dangling instead of disappearing).
    • Improved authorization enforcement for document deletion via real-time workspace sync.
  • Tests
    • Expanded end-to-end coverage for cleanup reconciliation, recovery/ack behavior, indexing/embedding reconciliation, comment object deletion, and permissions.

@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bf0e9e0a-539d-42e8-897a-c4defd2fcf1d

📥 Commits

Reviewing files that changed from the base of the PR and between 84e968f and 2916d3d.

📒 Files selected for processing (1)
  • packages/backend/native/src/runtime/storage_runtime/document_cleanup.rs

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.


📝 Walkthrough

Walkthrough

Document cleanup adds native reconciliation and deferred deletion for missing documents, versioned downstream effects, storage job orchestration, and validation across runtime, search, Copilot, synchronization, and editor reference behavior.

Changes

Document cleanup and storage reconciliation

Layer / File(s) Summary
Runtime contracts and current document state
packages/backend/native/index.d.ts, packages/backend/native/src/runtime/types.rs, packages/backend/native/src/runtime/sql/*, packages/backend/native/src/runtime/storage_runtime/mod.rs
Adds cleanup result contracts and persistence tables, removes direct backend storage deletion, and centralizes current document reconstruction from snapshots and updates.
Native reconciliation and cleanup execution
packages/backend/native/src/runtime/storage_runtime/document_cleanup.rs, packages/backend/native/src/runtime/storage_runtime/blob_*.rs, packages/backend/native/src/runtime/error.rs
Reconciles missing documents, claims candidates with serialization retries, deletes related rows, processes comment objects, records effects, and updates storage reconciliation checkpoints.
Storage job orchestration and live document semantics
packages/backend/server/src/core/storage-runtime/provider.ts, packages/backend/server/src/core/storage/blob-job.ts, packages/backend/server/src/core/utils/*, packages/backend/server/src/core/doc/adapters/workspace.ts
Adds provider wrappers and scheduled jobs, dispatches cleanup effects, records health metrics, updates live-document extraction, and makes adapter deletion a no-op.
Search and Copilot effect reconciliation
packages/backend/server/src/plugins/indexer/*, packages/backend/server/src/plugins/copilot/*, packages/backend/server/src/models/copilot-context.ts
Reconciles restored or missing documents in search and Copilot, purges embeddings, acknowledges versioned effects, and removes legacy deletion jobs.
Validation coverage
packages/backend/native/src/runtime/storage_runtime/document_cleanup.rs, packages/backend/server/src/core/storage/__tests__/blob-job.spec.ts, packages/backend/server/src/plugins/*/__tests__/*, blocksuite/integration-test/src/__tests__/main/editor-semantics.spec.ts
Adds integration and job tests for cleanup execution, effect acknowledgement, permissions, restored documents, and dangling references.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant StorageCron
  participant StorageBlobJob
  participant StorageRuntime
  participant SearchIndexer
  participant CopilotEmbedding
  StorageCron->>StorageBlobJob: enqueue document cleanup execution
  StorageBlobJob->>StorageRuntime: execute cleanup candidates
  StorageRuntime-->>StorageBlobJob: return pending search and copilot effects
  StorageBlobJob->>SearchIndexer: enqueue search reconciliation
  StorageBlobJob->>CopilotEmbedding: enqueue Copilot reconciliation
  SearchIndexer->>StorageBlobJob: acknowledge search effect
  CopilotEmbedding->>StorageBlobJob: acknowledge Copilot effect
Loading

Possibly related PRs

Suggested labels: app:core, mod:native

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately reflects the main change: implementing server-side document garbage collection/cleanup.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 19, 2026

Copy link
Copy Markdown

Deploying blocksuite-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: 2916d3d
Status:⚡️  Build in progress...

View logs

@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: 3

🧹 Nitpick comments (1)
packages/backend/server/src/core/storage/blob-job.ts (1)

284-324: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Cleanup execution has no continuation, so backlogs drain one batch per invocation.

Unlike the sid-based sweeps and executeBlobCleanupCandidatesByMarkedRuns (which re-enqueue to continue), this handler runs a single batch of limit (default 100) candidates and returns. With only the 4AM daily trigger, a backlog larger than limit drains at ~100/day, and the document_cleanup_marked >= 10_000 health warning in recordDocumentCleanupHealth could stay latched for a long time. Consider re-enqueueing when a full batch was executed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/backend/server/src/core/storage/blob-job.ts` around lines 284 - 324,
Update executeDocumentCleanupCandidates to enqueue a continuation job when the
current invocation processes a full limit-sized batch, preserving the existing
effect processing and health recording. Reuse the same workspaceId,
gracePeriodDays, and limit parameters and avoid re-enqueuing when fewer than
limit candidates were executed.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/backend/native/src/runtime/storage_runtime/document_cleanup.rs`:
- Around line 660-674: The completion and deletion check must run after
`commentObjectsDone` is set in the `process_comment_objects` flow. Reuse the
existing ack-path logic that evaluates all completion flags and deletes the
`document_cleanup_candidates` row, ensuring it also handles cases where
search/copilot acknowledgements arrived first.
- Around line 821-837: Rename the query result variable `updated` to `_updated`
in the document cleanup effect acknowledgment flow, or inline it into
`debug_assert_eq!`, so release builds do not report an unused variable while
preserving the row-count assertion.

In `@packages/backend/server/src/plugins/indexer/job.ts`:
- Around line 76-103: Guard reconcileDocumentCleanup with the existing
config.indexer.enabled check before reading documents or calling
service.indexDoc/service.deleteDoc. Return early when indexing is disabled,
while keeping the queue.add ackDocumentCleanupEffect path outside the guard so
cleanup effects are always acknowledged.

---

Nitpick comments:
In `@packages/backend/server/src/core/storage/blob-job.ts`:
- Around line 284-324: Update executeDocumentCleanupCandidates to enqueue a
continuation job when the current invocation processes a full limit-sized batch,
preserving the existing effect processing and health recording. Reuse the same
workspaceId, gracePeriodDays, and limit parameters and avoid re-enqueuing when
fewer than limit candidates were executed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 96a5363d-cf17-48e9-93f7-9cd1ed5a935a

📥 Commits

Reviewing files that changed from the base of the PR and between 81df475 and 66db2ba.

📒 Files selected for processing (30)
  • blocksuite/integration-test/src/__tests__/main/editor-semantics.spec.ts
  • packages/backend/native/index.d.ts
  • packages/backend/native/src/runtime/backend_runtime/doc_storage.rs
  • packages/backend/native/src/runtime/backend_runtime/tests.rs
  • packages/backend/native/src/runtime/error.rs
  • packages/backend/native/src/runtime/migrations.rs
  • packages/backend/native/src/runtime/sql/runtime_migrations.sql
  • packages/backend/native/src/runtime/storage_runtime/blob_cleanup.rs
  • packages/backend/native/src/runtime/storage_runtime/blob_reconciliation.rs
  • packages/backend/native/src/runtime/storage_runtime/doc_blob_refs.rs
  • packages/backend/native/src/runtime/storage_runtime/document_cleanup.rs
  • packages/backend/native/src/runtime/storage_runtime/mod.rs
  • packages/backend/native/src/runtime/types.rs
  • packages/backend/server/src/__tests__/copilot/copilot.spec.ts
  • packages/backend/server/src/__tests__/sync/gateway.spec.ts
  • packages/backend/server/src/core/doc/adapters/workspace.ts
  • packages/backend/server/src/core/storage-runtime/provider.ts
  • packages/backend/server/src/core/storage/__tests__/blob-job.spec.ts
  • packages/backend/server/src/core/storage/blob-job.ts
  • packages/backend/server/src/core/utils/__tests__/blocksute.spec.ts
  • packages/backend/server/src/core/utils/blocksuite.ts
  • packages/backend/server/src/models/copilot-context.ts
  • packages/backend/server/src/plugins/copilot/embedding/job.ts
  • packages/backend/server/src/plugins/copilot/embedding/types.ts
  • packages/backend/server/src/plugins/copilot/session.ts
  • packages/backend/server/src/plugins/indexer/__tests__/job.spec.ts
  • packages/backend/server/src/plugins/indexer/__tests__/service.spec.ts
  • packages/backend/server/src/plugins/indexer/index.ts
  • packages/backend/server/src/plugins/indexer/job.ts
  • packages/backend/server/src/plugins/indexer/service.ts
💤 Files with no reviewable changes (4)
  • packages/backend/server/src/plugins/indexer/service.ts
  • packages/backend/server/src/plugins/indexer/tests/service.spec.ts
  • packages/backend/native/src/runtime/backend_runtime/doc_storage.rs
  • packages/backend/server/src/plugins/copilot/session.ts

Comment thread packages/backend/native/src/runtime/storage_runtime/document_cleanup.rs Outdated
Comment thread packages/backend/server/src/plugins/indexer/job.ts

@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.

♻️ Duplicate comments (1)
packages/backend/server/src/plugins/indexer/job.ts (1)

76-103: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Guard reconcileDocumentCleanup when the indexer is disabled.

The executeDocumentCleanupCandidates always enqueues this job. If config.indexer.enabled is false, this handler should skip loading the root document and updating the search state, but it must still enqueue the ackDocumentCleanupEffect job to ensure the cleanup effect is acknowledged.

💡 Proposed fix
   `@OnJob`('indexer.reconcileDocumentCleanup')
   async reconcileDocumentCleanup({
     workspaceId,
     docId,
     cleanupVersion,
   }: Jobs['indexer.reconcileDocumentCleanup']) {
-    const root = await this.doc.getDoc(workspaceId, workspaceId);
-    if (!root) {
-      throw new Error(`workspace root ${workspaceId} not found`);
-    }
-    const live = readAllDocIdsFromWorkspaceSnapshot(root.bin, true).includes(
-      docId
-    );
-    if (live) {
-      if (!(await this.doc.getDoc(workspaceId, docId))) {
-        throw new Error(`restored document ${workspaceId}/${docId} not found`);
-      }
-      await this.service.indexDoc(workspaceId, docId);
-    } else {
-      await this.service.deleteDoc(workspaceId, docId);
+    if (this.config.indexer.enabled) {
+      const root = await this.doc.getDoc(workspaceId, workspaceId);
+      if (!root) {
+        throw new Error(`workspace root ${workspaceId} not found`);
+      }
+      const live = readAllDocIdsFromWorkspaceSnapshot(root.bin, true).includes(
+        docId
+      );
+      if (live) {
+        if (!(await this.doc.getDoc(workspaceId, docId))) {
+          throw new Error(`restored document ${workspaceId}/${docId} not found`);
+        }
+        await this.service.indexDoc(workspaceId, docId);
+      } else {
+        await this.service.deleteDoc(workspaceId, docId);
+      }
     }
     await this.queue.add('backendRuntime.ackDocumentCleanupEffect', {
       workspaceId,
       docId,
       cleanupVersion,
       effect: 'search',
     });
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/backend/server/src/plugins/indexer/job.ts` around lines 76 - 103,
Update reconcileDocumentCleanup to check config.indexer.enabled before loading
the workspace root or calling indexDoc/deleteDoc; when disabled, skip those
operations and still enqueue backendRuntime.ackDocumentCleanupEffect with the
existing workspaceId, docId, cleanupVersion, and search effect payload.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@packages/backend/server/src/plugins/indexer/job.ts`:
- Around line 76-103: Update reconcileDocumentCleanup to check
config.indexer.enabled before loading the workspace root or calling
indexDoc/deleteDoc; when disabled, skip those operations and still enqueue
backendRuntime.ackDocumentCleanupEffect with the existing workspaceId, docId,
cleanupVersion, and search effect payload.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 838a7c0d-40da-4b1c-86d0-2e81454bd6c5

📥 Commits

Reviewing files that changed from the base of the PR and between 66db2ba and 705da77.

📒 Files selected for processing (30)
  • blocksuite/integration-test/src/__tests__/main/editor-semantics.spec.ts
  • packages/backend/native/index.d.ts
  • packages/backend/native/src/runtime/backend_runtime/doc_storage.rs
  • packages/backend/native/src/runtime/backend_runtime/tests.rs
  • packages/backend/native/src/runtime/error.rs
  • packages/backend/native/src/runtime/migrations.rs
  • packages/backend/native/src/runtime/sql/runtime_migrations.sql
  • packages/backend/native/src/runtime/storage_runtime/blob_cleanup.rs
  • packages/backend/native/src/runtime/storage_runtime/blob_reconciliation.rs
  • packages/backend/native/src/runtime/storage_runtime/doc_blob_refs.rs
  • packages/backend/native/src/runtime/storage_runtime/document_cleanup.rs
  • packages/backend/native/src/runtime/storage_runtime/mod.rs
  • packages/backend/native/src/runtime/types.rs
  • packages/backend/server/src/__tests__/copilot/copilot.spec.ts
  • packages/backend/server/src/__tests__/sync/gateway.spec.ts
  • packages/backend/server/src/core/doc/adapters/workspace.ts
  • packages/backend/server/src/core/storage-runtime/provider.ts
  • packages/backend/server/src/core/storage/__tests__/blob-job.spec.ts
  • packages/backend/server/src/core/storage/blob-job.ts
  • packages/backend/server/src/core/utils/__tests__/blocksute.spec.ts
  • packages/backend/server/src/core/utils/blocksuite.ts
  • packages/backend/server/src/models/copilot-context.ts
  • packages/backend/server/src/plugins/copilot/embedding/job.ts
  • packages/backend/server/src/plugins/copilot/embedding/types.ts
  • packages/backend/server/src/plugins/copilot/session.ts
  • packages/backend/server/src/plugins/indexer/__tests__/job.spec.ts
  • packages/backend/server/src/plugins/indexer/__tests__/service.spec.ts
  • packages/backend/server/src/plugins/indexer/index.ts
  • packages/backend/server/src/plugins/indexer/job.ts
  • packages/backend/server/src/plugins/indexer/service.ts
💤 Files with no reviewable changes (4)
  • packages/backend/native/src/runtime/backend_runtime/doc_storage.rs
  • packages/backend/server/src/plugins/indexer/tests/service.spec.ts
  • packages/backend/server/src/plugins/copilot/session.ts
  • packages/backend/server/src/plugins/indexer/service.ts
🚧 Files skipped from review as they are similar to previous changes (22)
  • packages/backend/server/src/core/utils/blocksuite.ts
  • packages/backend/native/src/runtime/error.rs
  • packages/backend/server/src/core/doc/adapters/workspace.ts
  • packages/backend/server/src/plugins/indexer/index.ts
  • packages/backend/native/src/runtime/types.rs
  • packages/backend/server/src/tests/sync/gateway.spec.ts
  • blocksuite/integration-test/src/tests/main/editor-semantics.spec.ts
  • packages/backend/native/src/runtime/storage_runtime/blob_reconciliation.rs
  • packages/backend/server/src/models/copilot-context.ts
  • packages/backend/native/src/runtime/backend_runtime/tests.rs
  • packages/backend/server/src/tests/copilot/copilot.spec.ts
  • packages/backend/native/src/runtime/migrations.rs
  • packages/backend/native/src/runtime/storage_runtime/doc_blob_refs.rs
  • packages/backend/server/src/core/storage-runtime/provider.ts
  • packages/backend/native/src/runtime/sql/runtime_migrations.sql
  • packages/backend/native/index.d.ts
  • packages/backend/native/src/runtime/storage_runtime/mod.rs
  • packages/backend/server/src/plugins/indexer/tests/job.spec.ts
  • packages/backend/native/src/runtime/storage_runtime/blob_cleanup.rs
  • packages/backend/server/src/core/storage/tests/blob-job.spec.ts
  • packages/backend/server/src/plugins/copilot/embedding/job.ts
  • packages/backend/server/src/core/storage/blob-job.ts

@codecov

codecov Bot commented Jul 19, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 82.45033% with 53 lines in your changes missing coverage. Please review.
✅ Project coverage is 61.01%. Comparing base (81df475) to head (2916d3d).
⚠️ Report is 1 commits behind head on canary.

Files with missing lines Patch % Lines
...ackend/server/src/core/storage-runtime/provider.ts 22.22% 21 Missing ⚠️
...ckages/backend/server/src/core/storage/blob-job.ts 90.34% 17 Missing ⚠️
packages/backend/server/src/plugins/indexer/job.ts 79.54% 9 Missing ⚠️
...ackend/server/src/plugins/copilot/embedding/job.ts 82.35% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           canary   #15282      +/-   ##
==========================================
+ Coverage   60.70%   61.01%   +0.31%     
==========================================
  Files        3311     3311              
  Lines      191719   191909     +190     
  Branches    28257    28319      +62     
==========================================
+ Hits       116379   117092     +713     
+ Misses      71539    71031     -508     
+ Partials     3801     3786      -15     
Flag Coverage Δ
server-test 81.07% <82.45%> (+0.39%) ⬆️
unittest 35.82% <ø> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot mentioned this pull request Jul 19, 2026
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant