Add Namespaces::StatePropagationIterator
What does this MR do and why?
Adds Namespaces::StatePropagationIterator, a subclass of Gitlab::Database::NamespaceEachBatch, as part of Phase 2: Build state-aware tree iterator with boundary enforcement.
The iterator extends the existing DFS traversal with a state_filter parameter. It overrides walk_down and next_elements to inject a WHERE state IN (...) clause into the LATERAL subqueries, so the traversal prunes entire subtrees rooted at namespaces whose state is not in the filter — without visiting or modifying them.
This is the boundary enforcement layer from ADR 003: for example, an archive propagation will skip over a deletion_scheduled subgroup and all of its descendants, leaving them untouched.
Relates to #599293 (closed)
References
Query plans
The iterator reuses the recursive CTE structure from NamespaceEachBatch. The only SQL difference is the state IN (...) predicate added to the two LATERAL subqueries.
walk_down — descend to first matching child: https://postgres.ai/console/gitlab/gitlab-production-main/sessions/52047/commands/153336
next_elements — advance to next matching sibling: https://postgres.ai/console/gitlab/gitlab-production-main/sessions/52047/commands/153338
Screenshots or screen recordings
Not applicable — no UI changes.
How to set up and validate locally
Run the model specs:
bundle exec rspec spec/models/namespaces/state_propagation_iterator_spec.rbMR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
Related to #599293 (closed)