fix(number-pool): list inherited numbers on each branch [IFC-3446]

Merged
AJ
12d ago
+361-60

A branch that inherits a number unchanged is missing from the pool allocations list

When a number is allocated on main and a branch is created afterwards, the allocations list shows the number on main only. Filtering the list by that branch shows nothing for the number, although reading the object on the branch gives it. After main changes the number, a row for the branch appears although nothing changed on the branch.

This PR lists a number on every live branch that holds it, with one row per number and branch (solution 1 in the issue). It does not change the shape of the GraphQL result.

Closes IFC-3446

Changes to the allocations queries

What users and API clients view differently:

  • InfrahubNumberPoolAllocations lists a number on each live branch that holds it, including a branch created after the number that never wrote the attribute. Filtering by that branch returns the number, and count includes these rows.
  • InfrahubResourcePoolAllocated returns the same rows as before this PR: it does not list a number on a branch that inherits it while the default branch still holds it.
  • The utilization figures do not change.

Implementation:

  • NumberPoolGetAllocated takes include_inherited_branches (default True), which adds the existing INHERITED_OPEN_VALUES_QUERY clause. NumberUtilizationGetter and InfrahubResourcePoolAllocated pass False.
  • The query groups its rows by Attribute before it looks up the holding object, so the holding Node and the IS_RESERVED edge's properties are read once per number, not once per number and branch.

What stays the same: no GraphQL schema change, no frontend change, no Python SDK change.

Cost of the extra rows

  • A number held on the default branch gains one row for each live branch created after it that has no value edge of its own on the attribute. Live branches include merged branches that were not deleted.
  • The sort and count read every row, so each page of InfrahubNumberPoolAllocations reads about numbers Ɨ branches rows.
  • Measured with PROFILE on a local Neo4j, 200 numbers and 20 branches: 51,719 database hits with the first commit, 15,843 with the third. With 1,000 numbers and 30 branches (31,000 rows), the count query takes 98,409 database hits. Larger datasets were not measured.

How to review

  1. backend/infrahub/core/query/resource_manager.py, NumberPoolGetAllocated.
  2. backend/infrahub/graphql/queries/resource_manager.py and backend/infrahub/pools/number.py: the two callers that pass include_inherited_branches=False.
  3. Tests. Most changes are updated expectations: the existing datasets create a branch after the numbers on main, so each such number gains a row for that branch. TestNumberPoolGetAllocatedOnInheritingBranches is new and covers four cases:
    • a number inherited unchanged;
    • a number changed on main after the branch was created;
    • a number changed on the branch;
    • a number created after the branch.

Impact

  • Backward compatibility: InfrahubNumberPoolAllocations is not released (it is not on stable, v1.11.8). Its rows and count grow as described above. InfrahubResourcePoolAllocated returns the same rows as on release-1.12.
  • Changelog: no fragment. The allocations list first ships in 1.12, and changelog/+ifc-3362-number-pool-body.changed.md already describes it as showing each number's branch.

Checklist

  • Tests added/updated
  • Changelog entry added (not needed, see Impact)
  • External docs updated (no change needed)
  • Internal .md docs updated (no change needed: the contract in dev/specs/ifc-3185-number-pool-scopes/contracts/graphql-number-pool-queries.md already states one row per branch)
  • I have reviewed AI generated content

šŸ¤– Generated with Claude Code