Skip to content

Store extra metadata in splits for disaster recovery - #6689

Open
guilload wants to merge 2 commits into
mainfrom
guilload/recovery-metadata
Open

Store extra metadata in splits for disaster recovery#6689
guilload wants to merge 2 commits into
mainfrom
guilload/recovery-metadata

Conversation

@guilload

@guilload guilload commented Aug 13, 2026

Copy link
Copy Markdown
Member

Description

Store extra metadata in splits so one can (somewhat) recover the metastore database from storage.

How was this PR tested?

Add unit tests and integrations
Tested locally:

  • wrote two splits locally with legacy format
  • wrote two splits locally with new format
  • performed searches against old splits, new splits, all splits

@guilload
guilload requested review from a team as code owners August 13, 2026 21:56
@guilload
guilload marked this pull request as draft August 13, 2026 21:56
@guilload
guilload force-pushed the guilload/recovery-metadata branch 3 times, most recently from a63634d to 17af55c Compare August 17, 2026 21:07
@guilload
guilload marked this pull request as ready for review August 17, 2026 21:25
@guilload
guilload force-pushed the guilload/recovery-metadata branch from 17af55c to 4248627 Compare August 17, 2026 22:00
@guilload
guilload requested a review from Mallets August 18, 2026 19:10
@guilload
guilload force-pushed the guilload/recovery-metadata branch from 4248627 to 52ed858 Compare August 18, 2026 20:07

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

https://github.com/quickwit-oss/quickwit/blob/52ed8587277078e2b89ca0056b98a843d9f60f79/quickwit-metastore/src/split_metadata.rs#L232
P2 Badge Assign recovered splits to a merge pipeline

When a disaster-recovery importer publishes the SplitMetadata returned here, every restored split has an empty node ID. merge_planner::belongs_to_pipeline requires an exact node-ID match, so these splits never belong to any real merge pipeline and immature recovered splits will no longer be compacted. Preserve the original node ID in the recovery payload or require the importer to supply a target node ID during reconstruction.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@guilload
guilload force-pushed the guilload/recovery-metadata branch from 52ed858 to d16610a Compare August 18, 2026 20:27
counters.num_staged_splits.fetch_add(split_metadata_list.len() as u64, Ordering::SeqCst);
counters
.num_staged_splits
.fetch_add(split_metadata_list.len() as u64, Ordering::SeqCst);

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.

nit (not related to this PR): we don't need Ordering::SeqCst for a counter, a Ordering::Relaxed is enough.

/// ```text
/// [bundle metadata (`BundleFileRanges`)][bundle metadata length]
/// ```
pub async fn read_split_footer(

@Mallets Mallets Aug 19, 2026

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.

For trailer-based splits locate_split_footer_range validates the absolute footer start but not the footer's internal structure. A malformed trailer or corrupted nested length can therefore cause an invalid slice access in read_split_footer and to panic.

The above is fine during normal operations or disaster recovery from an intact object store.
However, it could make disaster recovery harder to achieve in case some of splits gets corrupted.

I don't think any changes should be made to this PR but it's worth pointing it out.

Comment thread quickwit/quickwit-proto/src/metastore/mod.rs Outdated
Comment thread quickwit/quickwit-proto/src/metastore/mod.rs Outdated
Comment thread quickwit/quickwit-storage/src/bundle_storage.rs Outdated

fn deserialize_split_footer_trailer(trailer: &[u8]) -> anyhow::Result<Option<u64>> {
if trailer.len() != SPLIT_FOOTER_TRAILER_NUM_BYTES
|| &trailer[12..] != SPLIT_FOOTER_TRAILER_MAGIC

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.

nit: same comment as above on manual slices indexes and the potential usage of Reader/bytes::Buf.

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

LGTM

I validated this PR on a live cluster and all the necessary metadata are stored in the splits, resulting in a correct metastore backfilling.

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.

2 participants