Skip to main content

Module migration

Module migration 

Source
Expand description

Schema versioning and migration support for SqliteTaskStore.

This module provides a lightweight, forward-only migration runner that tracks applied schema versions in a schema_versions table. Migrations are defined as plain SQL strings and are executed inside transactions for atomicity.

§Concurrency

Each migration runs inside a BEGIN EXCLUSIVE transaction, which acquires a database-level write lock before reading. This prevents concurrent migration runners from both seeing the same version as unapplied and attempting to apply it simultaneously.

§Built-in migrations

VersionDescription
1Initial schema — tasks table with indexes on context_id and state
2Add created_at column to tasks table
3Add composite index on (context_id, state) for combined filter queries
4Add (updated_at DESC, id DESC) index for list ordering
5Add task_artifact_appends — the journal streaming appends are written to
6Add idempotency_keys — the index client-supplied send keys are claimed in
7Add task_events — the per-task log of what the agent emitted

This table listed 1 to 3 while seven existed — the failure mode of a list maintained by hand beside one maintained by the compiler. The test below fails if the two stop agreeing on how many there are.

SQLite’s ALTER TABLE has no ADD CONSTRAINT, so a CHECK in a table’s DDL reaches only databases built after it. task_events gained CHECK (seq > 0) in 0.13 and migration 7 carries it — that migration creates the table, sharing the constant with from_pool — but a database that already ran migration 7 keeps the unconstrained table. Correcting it means a full table rebuild for a constraint on values this crate does not write. pg_migration’s version 6 does it on PostgreSQL, which has ALTER TABLE ... ADD CONSTRAINT.

§Example

use a2a_protocol_server::store::migration::MigrationRunner;
use sqlx::sqlite::SqlitePoolOptions;

let pool = SqlitePoolOptions::new()
    .connect("sqlite:tasks.db")
    .await?;

let runner = MigrationRunner::new(pool);
let applied = runner.run_pending().await?;
println!("Applied migrations: {applied:?}");

Structs§

Migration
A single schema migration.
MigrationRunner
Runs schema migrations against a SQLite database.

Statics§

BUILTIN_MIGRATIONS
Built-in migrations for the SqliteTaskStore schema.