This is an automated email from the ASF dual-hosted git repository. hubcio pushed a commit to branch fix/server-ng-purge-partition-plane in repository https://gitbox.apache.org/repos/asf/iggy.git
commit 36a0012625eafac718db0ac788ee8a4d1bf72dd4 Author: Hubert Gruszecki <[email protected]> AuthorDate: Tue Jul 28 09:42:56 2026 +0200 fix(server-ng): wake reconciler on purge and truncate commits Purge and truncate commit without changing the partition set, so they never fired a MetadataCommitTick. Their on-disk effect is enforced only by reconcile_partition_purges and reconcile_segment_truncations, which run when a pass runs, so the effect was deferred to the periodic safety tick, stretching a purge's client-visible tail to a full reconcile_periodic_interval. DeleteSegments stays out by design: the leader rewrites it into TruncatePartition before journaling, so no commit carries it. --- core/server-ng/src/bootstrap.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/core/server-ng/src/bootstrap.rs b/core/server-ng/src/bootstrap.rs index 9fe565c89..677e30eca 100644 --- a/core/server-ng/src/bootstrap.rs +++ b/core/server-ng/src/bootstrap.rs @@ -3116,6 +3116,15 @@ fn make_metadata_commit_notifier( /// before journaling, so a committed prepare only ever carries the /// assignment-bearing variant. Kept as defense-in-depth against a future /// commit path that emits a bare op. +/// +/// "Partition-shape" is not only the partition SET: the purge and truncate +/// ops leave the set intact but advance per-partition state (purge +/// generation, delete watermark) that only the reconciler enforces on disk. +/// Omitting them defers the on-disk effect to the periodic safety tick, +/// stretching a purge's client-visible tail to a full +/// `reconcile_periodic_interval`. `DeleteSegments` is absent by design: the +/// leader rewrites it into `TruncatePartition` before journaling, so no +/// commit ever carries it. const fn operation_triggers_partition_reconcile(op: Operation) -> bool { matches!( op, @@ -3126,6 +3135,9 @@ const fn operation_triggers_partition_reconcile(op: Operation) -> bool { | Operation::DeleteTopic | Operation::DeleteStream | Operation::DeletePartitions + | Operation::PurgeStream + | Operation::PurgeTopic + | Operation::TruncatePartition ) } @@ -3151,6 +3163,29 @@ mod tests { ); } + #[test] + fn reconciler_driven_ops_broadcast_a_commit_tick() { + // These commit without touching the partition set, so nothing else + // signals the reconciler: `reconcile_partition_purges` and + // `reconcile_segment_truncations` are the only code that turns them + // into on-disk effect, and they run only when a pass runs. Dropping + // one from the filter silently downgrades it to the periodic tick. + for op in [ + Operation::PurgeStream, + Operation::PurgeTopic, + Operation::TruncatePartition, + ] { + assert!( + operation_triggers_partition_reconcile(op), + "{op:?} is enforced by the reconciler and must wake it on commit" + ); + } + assert!( + !operation_triggers_partition_reconcile(Operation::CreateUser), + "ops with no partition-shape effect must stay off the broadcast" + ); + } + #[test] fn shutdown_on_drop_armed_flips_flag() { let flag = Arc::new(AtomicBool::new(false));
