fix: make FTS metadata loading retry-safe#7838
Conversation
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: QUIET Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
| Ok(serde_json::from_str::<InvertedIndexParams>(params)?) | ||
| } | ||
| Err(_) => { | ||
| Err(error) if error.is_not_found() => { |
There was a problem hiding this comment.
Legacy FTS indexes can still fail to open on S3 readers that have s3:GetObject but not s3:ListBucket. These indexes do not contain metadata.lance, and S3 returns 403 rather than 404 for a missing object when ListBucket is unavailable, so is_not_found() is false even though tokens.lance is readable. Could we probe the legacy tokens file when opening metadata fails, use the fallback only if that succeeds, and otherwise preserve the original metadata error? https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html
| None => { | ||
| let mut indices = self | ||
| .index_cache | ||
| .get_or_insert_with_key(metadata_key, || async { |
There was a problem hiding this comment.
get_or_insert_with_key does not preserve loader errors for coalesced waiters. Moka runs one initializer, but each caller owns a separate oneshot; when the loader fails, only the initializer receives the original timeout or permission error and the other callers return Internal("Failed to retrieve error from cache loader"). A five-caller repro produced one Timeout and four Internal errors. Could we fan out the same fallible result and add a concurrent failure test before using this path here?
Distributed FTS global-stats planning needs one immutable set of index segments and parsed tokenizer parameters per table snapshot. Concurrent cold callers currently race while reading index metadata, and
InvertedIndex::load_paramstreats everymetadata.lanceopen failure as a legacy index. A transient object-store error can therefore become a successful default-tokenizer fallback and be retained by an upper-layer cache.Make index-metadata cache misses use the existing fallible singleflight path and include the object-store identity in the cache key. Restrict the legacy tokens fallback to typed not-found errors, preserving that variant through shared-reader error cloning so timeouts and permission failures remain retryable errors.
This is the Lance-side prerequisite for the Sophon QN-owned FTS index snapshot cache in lancedb/sophon#6759.