This is an automated email from the ASF dual-hosted git repository. krishvishal pushed a commit to branch sim-workload-faults in repository https://gitbox.apache.org/repos/asf/iggy.git
commit 495db105cc0272d2c867ef9ea89c733220e1eaaf Author: Krishna Vishal <[email protected]> AuthorDate: Fri Aug 14 23:53:12 2026 +0530 fix(simulator): skip re-materialising a namespace the workload deleted `materialise_partition` seeded its namespace into committed metadata and then unwrapped the committed revision, which held only while nothing ever removed the stream or topic behind it. A metadata workload does remove them, and the seed's `CreatePartitions` is then a committed REJECTION rather than an error, so it reports nothing and the unwrap panicked on the next restart that re-materialised the group. Skip the group instead, and decide it before building anything: a rebooted server does not re-open a deleted partition's directory either, so a skipped group should leave behind neither a partition nor a routing row. Surfaced by metadata-plane crash/restart runs, which previously wedged before ever reaching a restart that re-materialised a deleted namespace. --- core/simulator/src/lib.rs | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/core/simulator/src/lib.rs b/core/simulator/src/lib.rs index 7d0ce2413..5d8a42f19 100644 --- a/core/simulator/src/lib.rs +++ b/core/simulator/src/lib.rs @@ -1032,6 +1032,22 @@ impl Simulator { fn materialise_partition(replica: &SimReplica, namespace: IggyNamespace) { let shard_count = u32::try_from(replica.shards.len()).expect("shard count fits u32"); let owner = calculate_shard_assignment(&namespace, shard_count); + // Commit the namespace before anything else: a partition the metadata plane + // never heard of is a shape production cannot produce, and the shard refuses + // to serve client traffic whose routing-row epoch it cannot match against a + // committed `created_revision`. + let streams = replica.shards[0].plane.metadata().mux_stm.streams(); + streams.seed_namespace(namespace, namespace.inner()); + // No committed revision means the seed could not re-add the namespace, which + // happens once a metadata workload has deleted its stream or topic: the seed's + // `CreatePartitions` is then a committed REJECTION, not an error, so it + // reports nothing. Skip the group rather than build a partition no committed + // metadata names -- a rebooted server does not re-open a deleted partition's + // directory either. Checked before the build so a skipped group leaves + // neither a partition nor a routing row behind. + let Some(epoch) = streams.created_revision_for_namespace(namespace) else { + return; + }; // One store per group, minted on first materialisation and reused on every // later one, so the recorded view survives a replica restart. let superblock = Rc::clone( @@ -1055,15 +1071,6 @@ fn materialise_partition(replica: &SimReplica, namespace: IggyNamespace) { recovered_state, retained, ); - // Commit the namespace before stamping the rows: a partition the metadata - // plane never heard of is a shape production cannot produce, and the shard - // refuses to serve client traffic whose routing-row epoch it cannot match - // against a committed `created_revision`. - let streams = replica.shards[0].plane.metadata().mux_stm.streams(); - streams.seed_namespace(namespace, namespace.inner()); - let epoch = streams - .created_revision_for_namespace(namespace) - .expect("namespace committed by the seed above"); for shard in &replica.shards { shard.shards_table().insert( namespace,
