Repository navigation
Create and discard an archive database file #378
Description
Overview
Morango can create a new SQLite archive file with only the morango tables, and it can discard that file cleanly. This work is part of milestone M5.
Background & Motivation
The archive is a second Django database. Morango must open it at run time, add the morango tables with the normal migrations, and remove every trace of it after a failure. The work happens in a partial file, and only a completed export gets the final name.
Design: spec. Plan: implementation plan, Task 17.
Description & Expected Outcomes
Archive.create(path) refuses a path that exists. It writes to <path>.partial and replaces a stale partial file. It registers an archive alias with the prefix morango_archive_, and it turns on incremental auto-vacuum before the tables exist. Then it runs the morango migrations on the archive alias and makes sure that every morango table exists.
If a table is missing, a host router blocked the migration. In that case, create raises MorangoArchiveError with a message about the router requirement. Archive.discard() closes the connection, removes the archive alias, and deletes the partial file.
An ArchiveDatabase handle gives the archive alias to other code. Every query through this handle goes to the archive.
Deliverables & Contracts
The change delivers these capabilities:
ARCHIVE_ALIAS_PREFIX, with the value"morango_archive_".ArchiveDatabase, a subclass ofSyncDatabasewith a fixed alias.Archive.create(path)andArchive.discard().- The errors
MorangoArchiveErrorandMorangoArchiveExists.
Acceptance Criteria
-
createon a new path makes<path>.partialwith a table for every morango model. -
PRAGMA auto_vacuumon the new file returns 2 (incremental). -
createon an existing path raisesMorangoArchiveExists. -
createreplaces a stale<path>.partial. - If a router denies morango migrations on the prefix,
createraisesMorangoArchiveError, and no archive alias and no partial file remain. -
discardremoves the partial file and the archive alias, and a seconddiscarddoes nothing. - The full test suite passes.
Technical Pointers & Architecture
- Target Components / Context:
morango/sync/archive.py,morango/errors.py. - Related Patterns:
SyncDatabasefrom Explicit database handle for sync database access #365. The spike in Spike: prove that a Django-managed archive database works #362 records how alias registration and migrations work on Django 3.2. - Data Model & Schema Considerations: The archive uses the normal morango migrations, so its
django_migrationstable records its schema version. - Resilience & Failure Modes: Every failure after the alias registration must remove the archive alias and the partial file. Errors must propagate. A router that denies migration makes Django skip every table, record the migrations as applied, and raise no error (Spike: prove that a Django-managed archive database works #362). The table check is what detects it. Django connections are thread-local, so register, use and remove the alias on one thread.
Notes & Tradeoffs
- Dependencies: Blocked by: Spike: prove that a Django-managed archive database works #362 (spike), Explicit database handle for sync database access #365 (
SyncDatabase), Give archive metadata a typed, immutable form #377 (ArchiveManifest). Blocks: Prevent two exports to the same archive path #379, Give each archive its own morango instance identity #380, Store the certificate chain in archives without private keys #381, Finalize archives into a compact file at the final path #382. - Testing Requirements: Use
override_settings(DATABASE_ROUTERS=[...])for the router case. - Tradeoffs & Alternatives Considered: The
migratecommand sendspost_migrateto all apps, and the contenttypes app then needs its table in the archive. A direct call to the migration executor prevents this. - Compatibility & Migrations: Kolibri routers must allow morango migrations on aliases with the prefix.
Metadata
- Complexity: Medium
- Target Branch: release-v0.9.x
AI Usage
Drafted with Claude (Claude Code) from the approved design spec and implementation plan. The author reviewed the requirements, and the code references were checked against the release-v0.9.x codebase.
Activity