Skip to content

Commit 71f0d30

Browse files
g-talbotclaude
andauthored
fix: improve delete_metrics_splits error handling and doc comments (#6280)
* review: parquet_file singular, proto doc link, fix metastore accessor * style: fix rustfmt nightly comment wrapping in split metadata Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: use plain code span for proto reference to avoid broken rustdoc link Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 777a338 commit 71f0d30

2 files changed

Lines changed: 63 additions & 27 deletions

File tree

quickwit/quickwit-metastore/src/metastore/postgres/metastore.rs

Lines changed: 61 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2633,45 +2633,80 @@ impl MetastoreService for PostgresqlMetastore {
26332633
);
26342634

26352635
// Only delete splits that are marked for deletion
2636+
// Match the non-metrics delete_splits pattern: distinguish
2637+
// "not found" (warn + succeed) from "not deletable" (FailedPrecondition).
26362638
const DELETE_SPLITS_QUERY: &str = r#"
2637-
DELETE FROM metrics_splits
2638-
WHERE
2639-
index_uid = $1
2640-
AND split_id = ANY($2)
2641-
AND split_state = 'MarkedForDeletion'
2642-
RETURNING split_id
2639+
WITH input_splits AS (
2640+
SELECT input_splits.split_id, metrics_splits.split_state
2641+
FROM UNNEST($2::text[]) AS input_splits(split_id)
2642+
LEFT JOIN metrics_splits
2643+
ON metrics_splits.index_uid = $1
2644+
AND metrics_splits.split_id = input_splits.split_id
2645+
),
2646+
deleted AS (
2647+
DELETE FROM metrics_splits
2648+
USING input_splits
2649+
WHERE
2650+
metrics_splits.index_uid = $1
2651+
AND metrics_splits.split_id = input_splits.split_id
2652+
AND NOT EXISTS (
2653+
SELECT 1 FROM input_splits
2654+
WHERE split_state IN ('Staged', 'Published')
2655+
)
2656+
RETURNING metrics_splits.split_id
2657+
)
2658+
SELECT
2659+
(SELECT COUNT(*) FROM input_splits WHERE split_state IS NOT NULL) as num_found,
2660+
(SELECT COUNT(*) FROM deleted) as num_deleted,
2661+
COALESCE(
2662+
(SELECT ARRAY_AGG(split_id) FROM input_splits
2663+
WHERE split_state IN ('Staged', 'Published')),
2664+
ARRAY[]::text[]
2665+
) as not_deletable,
2666+
COALESCE(
2667+
(SELECT ARRAY_AGG(split_id) FROM input_splits
2668+
WHERE split_state IS NULL),
2669+
ARRAY[]::text[]
2670+
) as not_found
26432671
"#;
26442672

2645-
let deleted_split_ids: Vec<String> = sqlx::query_scalar(DELETE_SPLITS_QUERY)
2673+
let (num_found, num_deleted, not_deletable_ids, not_found_ids): (
2674+
i64,
2675+
i64,
2676+
Vec<String>,
2677+
Vec<String>,
2678+
) = sqlx::query_as(DELETE_SPLITS_QUERY)
26462679
.bind(request.index_uid())
26472680
.bind(&request.split_ids)
2648-
.fetch_all(&self.connection_pool)
2681+
.fetch_one(&self.connection_pool)
26492682
.await
26502683
.map_err(|sqlx_error| convert_sqlx_err(&request.index_uid().index_id, sqlx_error))?;
26512684

2652-
// Log if some splits were not deleted (either non-existent or not
2653-
// in MarkedForDeletion state). Delete is idempotent — we don't error
2654-
// for missing splits.
2655-
if deleted_split_ids.len() != request.split_ids.len() {
2656-
let not_deleted: Vec<String> = request
2657-
.split_ids
2658-
.iter()
2659-
.filter(|id| !deleted_split_ids.contains(id))
2660-
.cloned()
2661-
.collect();
2685+
if !not_deletable_ids.is_empty() {
2686+
let message = format!(
2687+
"splits `{}` are not deletable",
2688+
not_deletable_ids.join(", ")
2689+
);
2690+
let entity = EntityKind::Splits {
2691+
split_ids: not_deletable_ids,
2692+
};
2693+
return Err(MetastoreError::FailedPrecondition { entity, message });
2694+
}
26622695

2663-
if !not_deleted.is_empty() {
2664-
warn!(
2665-
index_uid = %request.index_uid(),
2666-
not_deleted = ?not_deleted,
2667-
"some metrics splits were not deleted (non-existent or not marked for deletion)"
2668-
);
2669-
}
2696+
if !not_found_ids.is_empty() {
2697+
warn!(
2698+
index_uid = %request.index_uid(),
2699+
not_found = ?not_found_ids,
2700+
"{} metrics splits were not found and could not be deleted",
2701+
not_found_ids.len()
2702+
);
26702703
}
26712704

2705+
let _ = (num_found, num_deleted); // used by the CTE logic
2706+
26722707
info!(
26732708
index_uid = %request.index_uid(),
2674-
deleted_count = deleted_split_ids.len(),
2709+
num_deleted,
26752710
"deleted metrics splits successfully"
26762711
);
26772712
Ok(EmptyResponse {})

quickwit/quickwit-parquet-engine/src/split/metadata.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,8 @@ pub struct MetricsSplitMetadata {
175175
/// 0 for newly ingested splits.
176176
pub num_merge_ops: u32,
177177

178-
/// RowKeys (sort-key min/max boundaries) as proto bytes.
178+
/// RowKeys (sort-key min/max boundaries) as serialized proto bytes
179+
/// (`sortschema::RowKeys` in `event_store_sortschema.proto`).
179180
/// None for pre-Phase-31 splits or splits without sort schema.
180181
pub row_keys_proto: Option<Vec<u8>>,
181182

0 commit comments

Comments
 (0)