Database Schema Changes¶
Klangk's SQLite schema evolves through ordered, once-only migrations:
an append-only list in
src/klangk/klangk/model/migrations/__init__.py,
applied automatically at startup (init_db) and recorded in the
schema_migrations table. If a row's id is recorded there, its migration
never runs again.
Adding a migration¶
- Create
src/klangk/klangk/model/migrations/m00NN_<slug>.pyexposingmigration = Migration(N, "00NN_<slug>", apply), and append it to theMIGRATIONSlist in the package__init__.pyin id order. Never renumber, reorder, or edit a shipped migration — append a new one instead. applyreceives the DB connection (the sameexecute/commit/rollbacksurfaceinit_dbuses). The runner wraps it in oneBEGIN IMMEDIATEtransaction committed together with the record row — do not issue your ownBEGIN/COMMITinside a migration.- Add a test in
src/klangk/klangkd-tests/tests/test_migrations.py.
The historical CREATE TABLE IF NOT EXISTS pile in
klangk/model/schema.py is frozen as the pre-migration baseline; its
ad-hoc repair blocks are already-applied history and stay put.
Failure behavior (operators)¶
If a migration raises, its transaction — DDL included, because SQLite DDL
is transactional only under an explicit BEGIN — is rolled back and the
migration is not recorded. Startup fails; the next boot retries the
same migration. Prior migrations stay applied and recorded. A migration
that fails repeatedly (see the server log for
Applying schema migration <name>) means an operator must inspect the
database; nothing half-applied is left behind in the meantime.
Renaming a shipped migration is detected and refused at startup
(Migration names are frozen once shipped) — a silent rename would fork
history between the recorded name and the code.