feat(server): improve doc gc (#15363)

#### PR Dependency Tree


* **PR #15363** 👈

This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Improved validation of workspace roots and document projections, with
clearer failures for malformed or incomplete data.
  * Improved document reference rebuilding and cleanup reliability.
* Updated document update merging to better handle invalid binary data.

* **Performance**
* Avoided unnecessary document reconstruction when no updates are
pending.

* **Tests**
* Updated coverage for malformed workspace roots and document snapshot
parsing.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
DarkSky
2026-07-28 11:20:12 +08:00
committed by GitHub
parent b05f165820
commit cfc7bbb90f
6 changed files with 80 additions and 72 deletions
+13 -12
View File
@@ -3,7 +3,7 @@ use memory_indexer::{SearchHit, SnapshotData};
use napi_derive::napi;
use serde::Serialize;
use sqlx::Row;
use y_octo::DocOptions;
use y_octo::merge_updates_v1;
// Increment this whenever there is a breaking change in the index format or how
// updates are applied
@@ -120,7 +120,7 @@ impl SqliteDocStorage {
}
segments.extend(updates.into_iter().map(|update| update.bin.to_vec()));
merge_updates(segments, doc_id).map(Some)
merge_updates(segments).map(Some)
}
pub async fn init_index(&self) -> Result<()> {
@@ -249,7 +249,7 @@ impl SqliteDocStorage {
}
}
fn merge_updates(mut segments: Vec<Vec<u8>>, guid: &str) -> Result<Vec<u8>> {
fn merge_updates(mut segments: Vec<Vec<u8>>) -> Result<Vec<u8>> {
if segments.is_empty() {
return Err(ParseError::DocNotFound.into());
}
@@ -258,15 +258,9 @@ fn merge_updates(mut segments: Vec<Vec<u8>>, guid: &str) -> Result<Vec<u8>> {
return segments.pop().ok_or(ParseError::DocNotFound.into());
}
let mut doc = DocOptions::new().with_guid(guid.to_string()).build();
for update in segments.iter() {
doc
.apply_update_from_binary_v1(update)
.map_err(|_| ParseError::InvalidBinary)?;
}
let buffer = doc
.encode_update_v1()
let update = merge_updates_v1(segments).map_err(|_| ParseError::InvalidBinary)?;
let buffer = update
.encode_v1()
.map_err(|err| ParseError::ParserError(err.to_string()))?;
Ok(buffer)
@@ -317,6 +311,13 @@ mod tests {
.execute(&storage.pool)
.await
.unwrap();
sqlx::query(r#"INSERT INTO updates (doc_id, data, created_at) VALUES (?, ?, ?)"#)
.bind("demo-doc")
.bind(&[0, 0][..])
.bind(Utc::now().naive_utc())
.execute(&storage.pool)
.await
.unwrap();
let result = storage.crawl_doc_data("demo-doc").await.unwrap();