diff --git a/_sql/artcraft_migrations/20250708000000_create_tasks_table.sql b/_sql/artcraft_migrations/20250708000000_create_tasks_table.sql index 369d523c76..59a32c38bd 100644 --- a/_sql/artcraft_migrations/20250708000000_create_tasks_table.sql +++ b/_sql/artcraft_migrations/20250708000000_create_tasks_table.sql @@ -30,11 +30,17 @@ CREATE TABLE tasks ( provider_job_id TEXT, -- OPTIONAL. - -- An arbitrary payload the frontend can set. + -- Tell the job system which event(s) to send to the frontend + -- upon task completion. Comma-separated list of event names. + frontend_subscriber_event_names TEXT, + + -- OPTIONAL. + -- An arbitrary opaque identifier that frontend can set. frontend_subscriber_id TEXT, -- OPTIONAL. - -- A JSON payload for the frontend subscriber. + -- An opaque JSON payload set by the frontend subscriber that + -- will be re-emitted back to the frontend. frontend_subscriber_payload TEXT, created_at INTEGER NOT NULL DEFAULT (unixepoch('now')), diff --git a/crates/schema/database/sqlite_tasks/src/connection.rs b/crates/schema/database/sqlite_tasks/src/connection.rs index 2a46d832d0..7a7884f1a8 100644 --- a/crates/schema/database/sqlite_tasks/src/connection.rs +++ b/crates/schema/database/sqlite_tasks/src/connection.rs @@ -1,4 +1,6 @@ use errors::AnyhowResult; +use log::{error, info}; +use sqlx::migrate::MigrateError; use sqlx::sqlite::{SqliteConnectOptions, SqliteJournalMode}; use sqlx::{Pool, Sqlite, SqlitePool}; use std::path::Path; @@ -10,19 +12,20 @@ pub struct TaskDbConnection { impl TaskDbConnection { pub async fn connect_and_migrate>(database_file: P) -> AnyhowResult { - let connection_options = SqliteConnectOptions::new() - .filename(database_file) - .create_if_missing(true) - .journal_mode(SqliteJournalMode::Wal); + match run_migrations(&database_file).await { + Ok(pool) => return Ok(Self { pool }), + Err(err) => { + error!("Error running SQLite migrations: {:?}", err); + } + } - let pool = SqlitePool::connect_with(connection_options).await?; + info!("Deleting and recreating SQLite database at {:?}", database_file.as_ref()); - // Run migrations regardless of whether the database is new, SQLx will track which migrations - // have been run. - // The migrations text get compiled into the binary, so no worries about build inclusion. - // Since the task database is being treated as ephemeral, we can always run migrations without - // worrying about previous state if we simply blow away old versions of the schema. - sqlx::migrate!("../../../../_sql/artcraft_migrations").run(&pool).await?; + if let Err(err) = std::fs::remove_file(&database_file) { + error!("Error deleting SQLite database file: {:?}", err); + } + + let pool = run_migrations(database_file).await?; Ok(Self { pool }) } @@ -31,3 +34,21 @@ impl TaskDbConnection { &self.pool } } + +async fn run_migrations>(database_file: P) -> Result { + let connection_options = SqliteConnectOptions::new() + .filename(database_file) + .create_if_missing(true) + .journal_mode(SqliteJournalMode::Wal); + + let pool = SqlitePool::connect_with(connection_options).await?; + + // Run migrations regardless of whether the database is new, SQLx will track which migrations + // have been run. + // The migrations text get compiled into the binary, so no worries about build inclusion. + // Since the task database is being treated as ephemeral, we can always run migrations without + // worrying about previous state if we simply blow away old versions of the schema. + sqlx::migrate!("../../../../_sql/artcraft_migrations").run(&pool).await?; + + Ok(pool) +}