use std::future::Future;
use super::helpers::with_write_transaction;
use crate::errors::{DynoxideError, Result};
use crate::storage_backend::StorageBackend;
use crate::storage_backend::schema::{self, OpenMigrations};
pub(crate) async fn run_open_migrations<S: StorageBackend>(
storage: &S,
plan: OpenMigrations,
) -> Result<()> {
if let Some(version) = plan.newer_than_this_build {
return Err(DynoxideError::InternalServerError(
schema::newer_than_this_build(version),
));
}
if plan.rebuild_multi_attribute_gsis {
migrate_step(storage, schema::MULTI_ATTRIBUTE_KEYS, || async {
super::gsi::rebuild_multi_attribute_gsis(storage)
.await
.map(|_| ())
})
.await?;
}
if plan.recompute_vector_sizes {
migrate_step(storage, schema::VECTOR_BILLED_SIZES, || async {
super::vector_index::recompute_vector_table_sizes(storage)
.await
.map(|_| ())
})
.await?;
}
Ok(())
}
async fn migrate_step<S, F, Fut>(storage: &S, version: u32, step: F) -> Result<()>
where
S: StorageBackend,
F: FnOnce() -> Fut,
Fut: Future<Output = Result<()>>,
{
with_write_transaction(storage, async {
if storage
.recorded_schema_version()
.await?
.is_some_and(|recorded| recorded >= version)
{
return Ok(());
}
step().await?;
storage.record_schema_version(version).await?;
Ok(())
})
.await
}