Files
homelable/backend/tests
Pouzor b76519b0dd fix(db): keep nodes insertable when the 3.3.0 backfill cannot finish
Upgrading 3.2.0 -> 3.3.0 could leave a database where approving a device —
or creating any node — failed with `NOT NULL constraint failed: nodes.status`.

The 3.3.0 migration moves the device facts off `nodes` onto `device_inventory`
and then drops the columns. The drop is skipped when a node is still unlinked,
because those columns are the only remaining copy of its facts. But a 3.2.0
`nodes` declares `status`, `services`, `properties` and `show_hardware` NOT NULL
with no server-side default, and the 3.3.0 model no longer writes them — so a
skipped drop bricks every later INSERT.

It skipped because one node killed the whole backfill: the loop shared a single
session, so an IntegrityError raised by autoflush lost every link made before it.

- Give each node its own savepoint. A node whose merge violates a constraint is
  skipped and logged on its own; the rest still link. `skipped` joins the stats
  reported at boot.
- Relax NOT NULL on the retained legacy columns when the drop is skipped, so the
  database stays writable while later boots retry the backfill. Values are kept;
  only the constraint goes. Guarded on the PRAGMA notnull flag, so it runs once.
- Share one `_rebuild_nodes` between the drop and the relax: it restores
  `PRAGMA foreign_keys = ON` in a finally (the connection returns to the pool)
  and clears a `nodes_new` left by a failed attempt.
- Match IEEE addresses case-insensitively, and never write one another inventory
  row already owns — `device_inventory.ieee_address` is UNIQUE, and a duplicate
  is one way the backfill was raising in the first place.

Tests build the real v3.2.0 schema from the tag: the existing legacy-migration
fixture declares `status` nullable, which is why this reached a release.

Fixes #351

ha-relevant: no
2026-08-17 01:55:51 +02:00
..