Centralize durable schema migration ownership

This commit is contained in:
ms2k 2026-07-19 01:20:18 +09:00
commit 069f3813ae
9 changed files with 354 additions and 350 deletions

View file

@ -22,6 +22,7 @@ remora-durable.workspace = true
remora-identity = { path = "../remora-identity" }
remora-result = { path = "../remora-result" }
remora-runtime = { path = "../remora-runtime" }
remora-schema.workspace = true
remora-target = { path = "../remora-target" }
rustls = "=0.23.42"
rustls-pemfile = "=2.2.0"

View file

@ -1,33 +0,0 @@
CREATE TABLE live_event_history_state (
singleton BOOLEAN PRIMARY KEY DEFAULT TRUE CHECK (singleton),
floor_outbox_id BIGINT NOT NULL DEFAULT 0 CHECK (floor_outbox_id >= 0),
progress_poll_not_before TIMESTAMPTZ NOT NULL DEFAULT '-infinity'
);
INSERT INTO live_event_history_state (singleton) VALUES (TRUE);
CREATE TABLE live_progress_event_state (
job_id TEXT PRIMARY KEY REFERENCES jobs (job_id),
attempt_id TEXT NOT NULL,
fence BIGINT NOT NULL CHECK (fence BETWEEN 1 AND 9007199254740991),
progress_present BOOLEAN NOT NULL,
completed_bytes BIGINT,
total_bytes BIGINT,
completed_members BIGINT,
total_members BIGINT,
updated_at TIMESTAMPTZ NOT NULL,
CONSTRAINT live_progress_event_shape_check CHECK (
(
progress_present
AND completed_bytes IS NOT NULL
AND completed_members IS NOT NULL
)
OR (
NOT progress_present
AND completed_bytes IS NULL
AND total_bytes IS NULL
AND completed_members IS NULL
AND total_members IS NULL
)
)
);

View file

@ -1,10 +0,0 @@
CREATE TABLE live_event_tickets (
ticket_digest BYTEA PRIMARY KEY CHECK (octet_length(ticket_digest) = 32),
principal JSONB NOT NULL,
origin TEXT NOT NULL CHECK (origin <> ''),
created_at TIMESTAMPTZ NOT NULL,
expires_at TIMESTAMPTZ NOT NULL CHECK (expires_at > created_at)
);
CREATE INDEX live_event_tickets_expiry_idx
ON live_event_tickets (expires_at);

View file

@ -291,22 +291,7 @@ fn admission_service(
}
async fn migrate_all(pool: &PgPool) -> Result<(), RuntimeError> {
remora_durable::migrate(pool).await.map_err(runtime_error)?;
remora_identity::migrate(pool)
.await
.map_err(runtime_error)?;
remora_credentials::migrate(pool)
.await
.map_err(runtime_error)?;
remora_admission::migrate(pool)
.await
.map_err(runtime_error)?;
remora_attempt::migrate(pool).await.map_err(runtime_error)?;
remora_result::migrate(pool).await.map_err(runtime_error)?;
remora_deletion::migrate(pool)
.await
.map_err(runtime_error)?;
crate::migrate(pool).await.map_err(runtime_error)
remora_schema::migrate(pool).await.map_err(runtime_error)
}
fn start_maintenance(

View file

@ -1,10 +1,8 @@
mod application;
mod migrate;
mod public;
mod worker;
pub use application::{ApiApplication, ApiApplicationConfig};
pub use migrate::{migrate, migrator};
pub use public::{
PublicApiConfig, PublicApiServices, PublicApiState, configure_public_api,
prune_live_event_history,

View file

@ -1,16 +0,0 @@
use remora_durable::DurableError;
use sqlx::PgPool;
const MIGRATION_TABLE: &str = "_remora_api_migrations";
pub async fn migrate(pool: &PgPool) -> Result<(), DurableError> {
let mut migrator = sqlx::migrate!("./migrations");
migrator.dangerous_set_table_name(MIGRATION_TABLE);
migrator.run(pool).await.map_err(DurableError::from)
}
pub fn migrator() -> sqlx::migrate::Migrator {
let mut migrator = sqlx::migrate!("./migrations");
migrator.dangerous_set_table_name(MIGRATION_TABLE);
migrator
}

View file

@ -2,26 +2,22 @@ use std::{net::TcpListener, time::Duration};
use actix_web::{App, HttpServer, web};
use futures_util::{SinkExt as _, StreamExt as _};
use remora_admission::{AdmissionConfig, AdmissionService, migrate as admission_migrate};
use remora_admission::{AdmissionConfig, AdmissionService};
use remora_api::{
PublicApiConfig, PublicApiServices, PublicApiState, configure_public_api,
migrate as api_migrate, prune_live_event_history,
prune_live_event_history,
};
use remora_attempt::{AttemptConfig, AttemptService, migrate as attempt_migrate};
use remora_attempt::{AttemptConfig, AttemptService};
use remora_contracts::{EventFrameDto, ResyncReasonDto};
use remora_coordination::{
ActivateOptions, CoordinationStore, LeaseOwner, ProgressValue, StoreConfig,
};
use remora_credentials::{
CredentialRegistry, VaultClient, VaultConfig, migrate as credentials_migrate,
};
use remora_deletion::{
DeletionConfig, DeletionService, TargetRegistry, migrate as deletion_migrate,
};
use remora_credentials::{CredentialRegistry, VaultClient, VaultConfig};
use remora_deletion::{DeletionConfig, DeletionService, TargetRegistry};
use remora_domain::{BucketName, OpaqueId, TargetPrefix, TargetStoreId};
use remora_durable::{PoolConfig, connect, enqueue, migrate as durable_migrate};
use remora_identity::{DefaultTarget, migrate as identity_migrate};
use remora_result::migrate as result_migrate;
use remora_durable::{PoolConfig, connect, enqueue};
use remora_identity::DefaultTarget;
use remora_schema::migrate as migrate_schema;
use reqwest::{Client, StatusCode};
use serde_json::{Value, json};
use sqlx::PgPool;
@ -73,14 +69,7 @@ impl Harness {
)
.await
.unwrap();
durable_migrate(&pool).await.unwrap();
identity_migrate(&pool).await.unwrap();
credentials_migrate(&pool).await.unwrap();
admission_migrate(&pool).await.unwrap();
attempt_migrate(&pool).await.unwrap();
result_migrate(&pool).await.unwrap();
deletion_migrate(&pool).await.unwrap();
api_migrate(&pool).await.unwrap();
migrate_schema(&pool).await.unwrap();
sqlx::query("TRUNCATE TABLE jobs CASCADE")
.execute(&pool)
.await

View file

@ -1,12 +1,9 @@
use std::{net::TcpListener, time::Duration};
use actix_web::{App, HttpServer, web};
use remora_admission::{AdmissionConfig, AdmissionService, migrate as admission_migrate};
use remora_api::{
PublicApiConfig, PublicApiServices, PublicApiState, configure_public_api,
migrate as api_migrate,
};
use remora_attempt::{AttemptConfig, AttemptService, migrate as attempt_migrate};
use remora_admission::{AdmissionConfig, AdmissionService};
use remora_api::{PublicApiConfig, PublicApiServices, PublicApiState, configure_public_api};
use remora_attempt::{AttemptConfig, AttemptService};
use remora_contracts::{
AttemptPageDto, DeletionOperationDto, JobPageDto, JobResourceDto, ResultDescriptorDto,
ResultMemberPageDto, SourceCredentialDto,
@ -14,16 +11,12 @@ use remora_contracts::{
use remora_coordination::{
ActivateOptions, CoordinationStore, LeaseOwner, ProgressValue, StoreConfig,
};
use remora_credentials::{
CredentialRegistry, VaultClient, VaultConfig, migrate as credentials_migrate,
};
use remora_deletion::{
DeletionConfig, DeletionService, TargetRegistry, migrate as deletion_migrate,
};
use remora_credentials::{CredentialRegistry, VaultClient, VaultConfig};
use remora_deletion::{DeletionConfig, DeletionService, TargetRegistry};
use remora_domain::{BucketName, OpaqueId, TargetPrefix, TargetStoreId};
use remora_durable::{PoolConfig, connect, migrate as durable_migrate};
use remora_identity::{DefaultTarget, migrate as identity_migrate};
use remora_result::migrate as result_migrate;
use remora_durable::{PoolConfig, connect};
use remora_identity::DefaultTarget;
use remora_schema::migrate as migrate_schema;
use remora_target::{
CreateObjectRequest, TargetStore, TargetStoreConfig, attempt_manifest_key_in,
attempt_object_key_in,
@ -64,14 +57,7 @@ impl Harness {
)
.await
.unwrap();
durable_migrate(&pool).await.unwrap();
identity_migrate(&pool).await.unwrap();
credentials_migrate(&pool).await.unwrap();
admission_migrate(&pool).await.unwrap();
attempt_migrate(&pool).await.unwrap();
result_migrate(&pool).await.unwrap();
deletion_migrate(&pool).await.unwrap();
api_migrate(&pool).await.unwrap();
migrate_schema(&pool).await.unwrap();
sqlx::query("TRUNCATE TABLE jobs CASCADE")
.execute(&pool)
.await

View file

@ -5,13 +5,11 @@ use rcgen::{
BasicConstraints, Certificate, CertificateParams, ExtendedKeyUsagePurpose, IsCa, Issuer,
KeyPair, KeyUsagePurpose,
};
use remora_admission::{
AdmissionConfig, AdmissionDecision, AdmissionService, migrate as admission_migrate,
};
use remora_admission::{AdmissionConfig, AdmissionDecision, AdmissionService};
use remora_api::{
AuthenticatedWorker, WorkerApiState, authenticate_rustls_worker, configure_worker_api,
};
use remora_attempt::{AttemptConfig, AttemptService, RecoveryConfig, migrate as attempt_migrate};
use remora_attempt::{AttemptConfig, AttemptService, RecoveryConfig};
use remora_contracts::{
ApiErrorDto, AttemptActivateRequestDto, AttemptCheckpointRequestDto, AttemptFailureOutcomeDto,
AttemptOutcomeDto, AttemptOutcomeRequestDto, AttemptProgressRequestDto, AttemptRenewRequestDto,
@ -24,13 +22,12 @@ use remora_contracts::{
StagingMultipartIdentityDto, StagingObjectIdentityDto, StagingWriteIntentDto,
};
use remora_coordination::{CoordinationStore, StoreConfig};
use remora_credentials::migrate as credentials_migrate;
use remora_domain::{
BucketName, JobPhase, OpaqueId, RuntimeFailureClass, StorageScope, TargetPrefix, TargetStoreId,
};
use remora_durable::{PoolConfig, connect, migrate as durable_migrate};
use remora_durable::{PoolConfig, connect};
use remora_identity::{DefaultTarget, Principal};
use remora_result::migrate as result_migrate;
use remora_schema::migrate as migrate_schema;
use remora_target::attempt_manifest_key_in;
use reqwest::{Certificate as ClientCertificate, Client, Identity};
use rustls::{
@ -59,11 +56,7 @@ impl Harness {
)
.await
.unwrap();
durable_migrate(&pool).await.unwrap();
credentials_migrate(&pool).await.unwrap();
admission_migrate(&pool).await.unwrap();
attempt_migrate(&pool).await.unwrap();
result_migrate(&pool).await.unwrap();
migrate_schema(&pool).await.unwrap();
sqlx::query("TRUNCATE TABLE jobs CASCADE")
.execute(&pool)
.await