appcore-sync-sqlite 0.1.0-alpha.5

Bounded SQLite persistence provider for AppCore synchronization state.
Documentation

appcore-sync-sqlite

English guide | Guia em português | Guide français

Optional post-1.0 SQLite persistence for AppCore synchronization state.

The crate implements the existing replication-log, outbox and checkpoint contracts. It also provides portable snapshots, bounded opaque tombstones, integrity inspection and verified online backup/restore. It never exposes a SQLite connection or accepts application SQL, tables, migrations or workflows.

Every database uses transactional internal schema V2, WAL, synchronous=FULL, a bounded connection pool, busy timeout, SQLite runtime limits and startup integrity validation. Unknown, unversioned and future schemas fail with NO MORE SUPPORTED PLEASE UPDATE.

Schema V2 adds bounded attempt counters and readiness timestamps to the outbox. peek and next_ready select count/byte metadata before reading BLOBs; stats contain no payload and a partial receipt deletes only an exact ordered prefix in one transaction. Enqueue measures the exact canonical JSON length first, then writes directly to a zeroblob; duplicate comparison, page reads and startup integrity validation also stream BLOB content. No encoded record-sized Vec<u8> coexists with the owned message. The stream buffers use the encoded record size up to fixed 64 KiB read and 1 MiB write ceilings, so a small record never reserves either maximum. A known schema V1 database migrates atomically with zeroed retry metadata. Preserve a pre-migration backup for rollback.

Portable snapshot creation moves the payloads read from SQLite into the V1 snapshot. Restore validates the caller-owned snapshot by reference, checks its aggregate payload against max_database_bytes before mutation and inserts directly from those borrowed records in one transaction. No complete in-memory replication log or second payload collection coexists with the snapshot.

The capability descriptor declares transactions, locking, snapshot, online_backup and multi_process. It deliberately does not declare streaming or multi_host.

This development crate is not selected by stable V1 manifests or by the SDK. Direct consumers opt in explicitly. See release/sqlite-sync-provider-v1.md.

cargo test -p appcore-sync-sqlite

Each pool connection and backup/restore auxiliary connection explicitly sets and checks cache_size=-2048 and mmap_size=0. The cache setting is a suggested 2 MiB target, not a hard heap cap. Eight default pool connections imply about 16 MiB of cache targets before auxiliary connections, queries, temporary data, WAL, payloads and allocator overhead. No process-global SQLite heap policy is changed. Temporary storage and WAL growth still require deployment budgets. See SQLite cache semantics.

Connections also request and verify temp_store=FILE before use, without changing the process-global temporary directory. This is not a guarantee that all temporary work goes to disk: SQLITE_TEMP_STORE=3 overrides the request (the bundled Android build uses it). SQLite may also retain temporary pages in cache. Deployments must inspect their build and budget private temporary storage, memory and cleanup; memory-only builds need a separate memory budget. See SQLite temporary storage.

WAL autocheckpoint at 1,000 pages is a trigger, not a disk-space cap. A held reader can prevent complete checkpointing while writers keep extending the WAL. An internal regression holds one read transaction across eight 1 MiB appends, observes more than 1,000 frames, then verifies truncation and intact records after releasing the reader and reopening. The test uses private SQL; it does not add a public checkpoint API. Bound readers/backups and monitor WAL and filesystem capacity in deployment; never delete a live WAL to reclaim space.

Replication-log pages now validate the aggregate length(payload) values before converting any page BLOB into a Rust Vec. Count, metadata and payload reads share one deferred transaction, so concurrent replacement cannot change the admitted page between passes. An oversized selected page still fails as a whole, preserving the existing contract. This adds a metadata pass and does not bound SQLite's internal cache or provide streaming output.

Stable documentation

Stable ID: ACR-026. See the supplemental architecture and integration guide. This permanent ID remains valid if the wiki page moves.