refactor logic around migrations to be more representative of reality

This commit is contained in:
Keagan McClelland
2021-11-30 14:06:03 -07:00
committed by Aiden McClelland
parent e578062082
commit 351cef4141
2 changed files with 96 additions and 87 deletions

View File

@@ -935,8 +935,8 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
..
} = prev
{
let mut configured = prev.status.configured;
if let Some(res) = prev_manifest
let prev_is_configured = prev.status.configured;
let prev_migration = prev_manifest
.migrations
.to(
ctx,
@@ -945,14 +945,8 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
&prev_manifest.version,
&prev_manifest.volumes,
)
.await?
{
configured &= res.configured;
}
if &prev.manifest.version != version {
cleanup(ctx, &prev.manifest.id, &prev.manifest.version).await?;
}
if let Some(res) = manifest
.map(futures::future::Either::Left);
let migration = manifest
.migrations
.from(
ctx,
@@ -961,10 +955,20 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
version,
&manifest.volumes,
)
.await?
{
configured &= res.configured;
}
.map(futures::future::Either::Right);
let viable_migration = if prev_manifest.version > manifest.version {
prev_migration.or(migration)
} else {
migration.or(prev_migration)
};
let configured = prev_is_configured
&& if let Some(f) = viable_migration {
f.await?.configured
} else {
false
};
if configured && manifest.config.is_some() {
crate::config::configure(
ctx,
@@ -1002,6 +1006,9 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
.collect::<BTreeSet<_>>(),
)
.await?;
if &prev.manifest.version != version {
cleanup(ctx, &prev.manifest.id, &prev.manifest.version).await?;
}
} else if let PackageDataEntry::Restoring { .. } = prev {
manifest
.backup
@@ -1051,12 +1058,12 @@ async fn handle_recovered_package(
version: &Version,
tx: &mut patch_db::Transaction<&mut patch_db::PatchDbHandle>,
) -> Result<(), Error> {
let configured = if let Some(res) = manifest
.migrations
.from(ctx, &recovered.version, pkg_id, version, &manifest.volumes)
.await?
let configured = if let Some(migration) =
manifest
.migrations
.from(ctx, &recovered.version, pkg_id, version, &manifest.volumes)
{
res.configured
migration.await?.configured
} else {
false
};

View File

@@ -1,5 +1,6 @@
use color_eyre::eyre::eyre;
use emver::VersionRange;
use futures::{Future, FutureExt, TryFutureExt};
use indexmap::IndexMap;
use patch_db::HasModel;
use serde::{Deserialize, Serialize};
@@ -20,76 +21,77 @@ pub struct Migrations {
}
impl Migrations {
#[instrument(skip(ctx))]
pub async fn from(
&self,
ctx: &RpcContext,
version: &Version,
pkg_id: &PackageId,
pkg_version: &Version,
volumes: &Volumes,
) -> Result<Option<MigrationRes>, Error> {
Ok(
if let Some((_, migration)) = self
.from
.iter()
.find(|(range, _)| version.satisfies(*range))
{
Some(
migration
.execute(
ctx,
pkg_id,
pkg_version,
Some("Migration"), // Migrations cannot be executed concurrently
volumes,
Some(version),
false,
None,
)
.await?
.map_err(|e| {
Error::new(eyre!("{}", e.1), crate::ErrorKind::MigrationFailed)
})?,
)
} else {
None
},
)
pub fn from<'a>(
&'a self,
ctx: &'a RpcContext,
version: &'a Version,
pkg_id: &'a PackageId,
pkg_version: &'a Version,
volumes: &'a Volumes,
) -> Option<impl Future<Output = Result<MigrationRes, Error>> + 'a> {
if let Some((_, migration)) = self
.from
.iter()
.find(|(range, _)| version.satisfies(*range))
{
Some(
migration
.execute(
ctx,
pkg_id,
pkg_version,
Some("Migration"), // Migrations cannot be executed concurrently
volumes,
Some(version),
false,
None,
)
.map(|r| {
r.and_then(|r| {
r.map_err(|e| {
Error::new(eyre!("{}", e.1), crate::ErrorKind::MigrationFailed)
})
})
}),
)
} else {
None
}
}
#[instrument(skip(ctx))]
pub async fn to(
&self,
ctx: &RpcContext,
version: &Version,
pkg_id: &PackageId,
pkg_version: &Version,
volumes: &Volumes,
) -> Result<Option<MigrationRes>, Error> {
Ok(
if let Some((_, migration)) =
self.to.iter().find(|(range, _)| version.satisfies(*range))
{
Some(
migration
.execute(
ctx,
pkg_id,
pkg_version,
Some("Migration"),
volumes,
Some(version),
false,
None,
)
.await?
.map_err(|e| {
Error::new(eyre!("{}", e.1), crate::ErrorKind::MigrationFailed)
})?,
)
} else {
None
},
)
pub fn to<'a>(
&'a self,
ctx: &'a RpcContext,
version: &'a Version,
pkg_id: &'a PackageId,
pkg_version: &'a Version,
volumes: &'a Volumes,
) -> Option<impl Future<Output = Result<MigrationRes, Error>> + 'a> {
if let Some((_, migration)) = self.to.iter().find(|(range, _)| version.satisfies(*range)) {
Some(
migration
.execute(
ctx,
pkg_id,
pkg_version,
Some("Migration"),
volumes,
Some(version),
false,
None,
)
.map(|r| {
r.and_then(|r| {
r.map_err(|e| {
Error::new(eyre!("{}", e.1), crate::ErrorKind::MigrationFailed)
})
})
}),
)
} else {
None
}
}
}