feat(store): import the dmfs database and make Room the default
Phase 4 of docs/OWN-STORE.md. OneShotImport reads databases/tasks.db directly — read-only, no provider, no ContentResolver — and writes it into Room in one verified transaction. dmfs row ids are remapped in two passes, because a parent can carry a higher _id than its child. The archive happens before the import, not after, and the import always replaces. That is what actually closes the crash window the plan's "flag *and* rename" is meant to cover: renaming last leaves the flag unset with tasks.db still in place, so the next launch imports a second copy. In this order every kill point re-enters correctly. Recurrence overrides are carried across as master_id/recurrence_id rather than ignored. dmfs stores them as ordinary rows sharing their master's _uid, so importing one as a second master would collide on the unique index and abort the whole import. autoMode now answers OWN, and a stored LOCAL reads as OWN — after the import the dmfs file has been renamed away, so someone who chose local storage explicitly must land on the store their data is now in. StartupGate holds the first store read until the mode has landed and the import has run; showing an upgrading user an empty app is the worst thing this migration could do. The backup rules take the database with its WAL sidecars and exclude the archive, and the app checkpoints on ON_STOP.
This commit is contained in:
@@ -1,4 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<full-backup-content>
|
||||
<!-- No file-based backups; settings live in DataStore which is backed up by default. -->
|
||||
<!--
|
||||
Agendula's own task store. Room runs in WAL mode and Auto Backup copies
|
||||
files without checkpointing, so the `-wal` sidecar can hold writes the
|
||||
`.db` alone does not — all three go in together, and the app checkpoints
|
||||
on ON_STOP so a restore is consistent either way.
|
||||
-->
|
||||
<include domain="database" path="agendula-tasks.db" />
|
||||
<include domain="database" path="agendula-tasks.db-wal" />
|
||||
<include domain="database" path="agendula-tasks.db-shm" />
|
||||
|
||||
<!--
|
||||
The archived dmfs database. Kept on the device for one release as the
|
||||
import's rollback path, but it is a copy of data that has already been
|
||||
imported, so backing it up would double every task in the archive.
|
||||
-->
|
||||
<exclude domain="database" path="tasks.db.imported" />
|
||||
|
||||
<!-- Settings live in DataStore, which is backed up by default. -->
|
||||
</full-backup-content>
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<data-extraction-rules>
|
||||
<cloud-backup>
|
||||
<!-- Allow DataStore backup, exclude nothing extra. -->
|
||||
<!-- See backup_rules.xml: the WAL sidecars travel with the database. -->
|
||||
<include domain="database" path="agendula-tasks.db" />
|
||||
<include domain="database" path="agendula-tasks.db-wal" />
|
||||
<include domain="database" path="agendula-tasks.db-shm" />
|
||||
<exclude domain="database" path="tasks.db.imported" />
|
||||
</cloud-backup>
|
||||
<device-transfer>
|
||||
<include domain="database" path="agendula-tasks.db" />
|
||||
<include domain="database" path="agendula-tasks.db-wal" />
|
||||
<include domain="database" path="agendula-tasks.db-shm" />
|
||||
<exclude domain="database" path="tasks.db.imported" />
|
||||
</device-transfer>
|
||||
</data-extraction-rules>
|
||||
|
||||
Reference in New Issue
Block a user