Feat bulk locking (#1422)

* Feat: Multi-lock capabilities add to config

* wip: RPC.rs fixes, new combinatoric

* wip: changes

* chore: More things that are bulk

* fix: Saving

* chore: Remove a dyn object

* chore: Add tests + remove unused

* Fix/feat  bulk locking (#1427)

* fix: health check

* fix: start/stop service

* fix: install/uninstall services

* chore: Fix the notifications

* fix: Version

* fix: Version as serde

* chore: Update to latest patch db

* chore: Change the htLock to something that makes more sense

* chore: Fix the rest of the ht

* "chore: More ht_lock":
This commit is contained in:
J M
2022-05-09 14:53:39 -06:00
committed by GitHub
parent 5d3bc8cfa5
commit 864555bcf0
26 changed files with 2080 additions and 743 deletions

View File

@@ -1,21 +1,65 @@
use std::collections::{BTreeMap, HashMap};
use bollard::image::ListImagesOptions;
use color_eyre::eyre::eyre;
use patch_db::{DbHandle, LockType, PatchDbHandle};
use patch_db::{DbHandle, LockReceipt, LockTargetId, LockType, PatchDbHandle, Verifier};
use sqlx::{Executor, Sqlite};
use tracing::instrument;
use super::{PKG_ARCHIVE_DIR, PKG_DOCKER_DIR};
use crate::context::RpcContext;
use crate::db::model::{CurrentDependencyInfo, InstalledPackageDataEntry, PackageDataEntry};
use crate::dependencies::reconfigure_dependents_with_live_pointers;
use crate::error::ErrorCollection;
use crate::s9pk::manifest::{Manifest, PackageId};
use crate::util::{Apply, Version};
use crate::Error;
use crate::db::model::{InstalledPackageDataEntry, PackageDataEntry};
use crate::{config::not_found, dependencies::reconfigure_dependents_with_live_pointers};
use crate::{config::ConfigReceipts, context::RpcContext};
use crate::{
db::model::AllPackageData,
s9pk::manifest::{Manifest, PackageId},
};
use crate::{db::model::CurrentDependencyInfo, error::ErrorCollection};
use crate::{
dependencies::DependencyErrors,
util::{Apply, Version},
};
use crate::{dependencies::TryHealReceipts, Error};
#[instrument(skip(ctx, db, deps))]
pub struct UpdateDependencyReceipts {
try_heal: TryHealReceipts,
dependency_errors: LockReceipt<DependencyErrors, String>,
manifest: LockReceipt<Manifest, String>,
}
impl UpdateDependencyReceipts {
pub async fn new<'a>(db: &'a mut impl DbHandle) -> Result<Self, Error> {
let mut locks = Vec::new();
let setup = Self::setup(&mut locks);
Ok(setup(&db.lock_all(locks).await?)?)
}
pub fn setup(locks: &mut Vec<LockTargetId>) -> impl FnOnce(&Verifier) -> Result<Self, Error> {
let dependency_errors = crate::db::DatabaseModel::new()
.package_data()
.star()
.installed()
.map(|x| x.status().dependency_errors())
.make_locker(LockType::Write)
.add_to_keys(locks);
let manifest = crate::db::DatabaseModel::new()
.package_data()
.star()
.installed()
.map(|x| x.manifest())
.make_locker(LockType::Write)
.add_to_keys(locks);
let try_heal = TryHealReceipts::setup(locks);
move |skeleton_key| {
Ok(Self {
dependency_errors: dependency_errors.verify(skeleton_key)?,
manifest: manifest.verify(skeleton_key)?,
try_heal: try_heal(skeleton_key)?,
})
}
}
}
#[instrument(skip(ctx, db, deps, receipts))]
pub async fn update_dependency_errors_of_dependents<
'a,
Db: DbHandle,
@@ -25,50 +69,31 @@ pub async fn update_dependency_errors_of_dependents<
db: &mut Db,
id: &PackageId,
deps: I,
receipts: &UpdateDependencyReceipts,
) -> Result<(), Error> {
for dep in deps {
if let Some(man) = &*crate::db::DatabaseModel::new()
.package_data()
.idx_model(&dep)
.and_then(|m| m.installed())
.map::<_, Manifest>(|m| m.manifest())
.get(db, true)
.await?
{
if let Some(man) = receipts.manifest.get(db, dep).await? {
if let Err(e) = if let Some(info) = man.dependencies.0.get(id) {
info.satisfied(ctx, db, id, None, dep).await?
info.satisfied(ctx, db, id, None, dep, &receipts.try_heal)
.await?
} else {
Ok(())
} {
let mut errs = crate::db::DatabaseModel::new()
.package_data()
.idx_model(&dep)
.expect(db)
let mut errs = receipts
.dependency_errors
.get(db, dep)
.await?
.installed()
.expect(db)
.await?
.status()
.dependency_errors()
.get_mut(db)
.await?;
.ok_or_else(not_found)?;
errs.0.insert(id.clone(), e);
errs.save(db).await?;
receipts.dependency_errors.set(db, errs, dep).await?
} else {
let mut errs = crate::db::DatabaseModel::new()
.package_data()
.idx_model(&dep)
.expect(db)
let mut errs = receipts
.dependency_errors
.get(db, dep)
.await?
.installed()
.expect(db)
.await?
.status()
.dependency_errors()
.get_mut(db)
.await?;
.ok_or_else(not_found)?;
errs.0.remove(id);
errs.save(db).await?;
receipts.dependency_errors.set(db, errs, dep).await?
}
}
}
@@ -127,24 +152,50 @@ pub async fn cleanup(ctx: &RpcContext, id: &PackageId, version: &Version) -> Res
errors.into_result()
}
#[instrument(skip(ctx, db))]
pub struct CleanupFailedReceipts {
package_data_entry: LockReceipt<PackageDataEntry, String>,
package_entries: LockReceipt<AllPackageData, String>,
}
impl CleanupFailedReceipts {
pub async fn new<'a>(db: &'a mut impl DbHandle) -> Result<Self, Error> {
let mut locks = Vec::new();
let setup = Self::setup(&mut locks);
Ok(setup(&db.lock_all(locks).await?)?)
}
pub fn setup(locks: &mut Vec<LockTargetId>) -> impl FnOnce(&Verifier) -> Result<Self, Error> {
let package_data_entry = crate::db::DatabaseModel::new()
.package_data()
.star()
.make_locker(LockType::Write)
.add_to_keys(locks);
let package_entries = crate::db::DatabaseModel::new()
.package_data()
.make_locker(LockType::Write)
.add_to_keys(locks);
move |skeleton_key| {
Ok(Self {
package_data_entry: package_data_entry.verify(skeleton_key).unwrap(),
package_entries: package_entries.verify(skeleton_key).unwrap(),
})
}
}
}
#[instrument(skip(ctx, db, receipts))]
pub async fn cleanup_failed<Db: DbHandle>(
ctx: &RpcContext,
db: &mut Db,
id: &PackageId,
receipts: &CleanupFailedReceipts,
) -> Result<(), Error> {
crate::db::DatabaseModel::new()
.package_data()
.lock(db, LockType::Write)
.await?;
let pde = crate::db::DatabaseModel::new()
.package_data()
.idx_model(id)
.expect(db)
let pde = receipts
.package_data_entry
.get(db, id)
.await?
.get(db, true)
.await?
.into_owned();
.ok_or_else(not_found)?;
if let Some(manifest) = match &pde {
PackageDataEntry::Installing { manifest, .. }
| PackageDataEntry::Restoring { manifest, .. } => Some(manifest),
@@ -173,26 +224,29 @@ pub async fn cleanup_failed<Db: DbHandle>(
match pde {
PackageDataEntry::Installing { .. } | PackageDataEntry::Restoring { .. } => {
crate::db::DatabaseModel::new()
.package_data()
.remove(db, id)
.await?;
let mut entries = receipts
.package_entries
.get(db, id)
.await?
.ok_or_else(not_found)?;
entries.0.remove(id);
receipts.package_entries.set(db, entries, id).await?;
}
PackageDataEntry::Updating {
installed,
static_files,
..
} => {
crate::db::DatabaseModel::new()
.package_data()
.idx_model(id)
.put(
receipts
.package_data_entry
.set(
db,
&PackageDataEntry::Installed {
PackageDataEntry::Installed {
manifest: installed.manifest.clone(),
installed,
static_files,
},
id,
)
.await?;
}
@@ -202,7 +256,7 @@ pub async fn cleanup_failed<Db: DbHandle>(
Ok(())
}
#[instrument(skip(db, current_dependencies))]
#[instrument(skip(db, current_dependencies, current_dependent_receipt))]
pub async fn remove_from_current_dependents_lists<
'a,
Db: DbHandle,
@@ -211,29 +265,69 @@ pub async fn remove_from_current_dependents_lists<
db: &mut Db,
id: &'a PackageId,
current_dependencies: I,
current_dependent_receipt: &LockReceipt<BTreeMap<PackageId, CurrentDependencyInfo>, String>,
) -> Result<(), Error> {
for dep in current_dependencies.into_iter().chain(std::iter::once(id)) {
if let Some(current_dependents) = crate::db::DatabaseModel::new()
.package_data()
.idx_model(dep)
.and_then(|m| m.installed())
.map::<_, BTreeMap<PackageId, CurrentDependencyInfo>>(|m| m.current_dependents())
.check(db)
.await?
{
if current_dependents
.clone()
.idx_model(id)
.exists(db, true)
.await?
{
current_dependents.remove(db, id).await?
if let Some(mut current_dependents) = current_dependent_receipt.get(db, dep).await? {
if current_dependents.remove(id).is_some() {
current_dependent_receipt
.set(db, current_dependents, dep)
.await?;
}
}
}
Ok(())
}
pub struct UninstallReceipts {
config: ConfigReceipts,
removing: LockReceipt<InstalledPackageDataEntry, ()>,
packages: LockReceipt<AllPackageData, ()>,
current_dependents: LockReceipt<BTreeMap<PackageId, CurrentDependencyInfo>, String>,
update_depenency_receipts: UpdateDependencyReceipts,
}
impl UninstallReceipts {
pub async fn new<'a>(db: &'a mut impl DbHandle, id: &PackageId) -> Result<Self, Error> {
let mut locks = Vec::new();
let setup = Self::setup(&mut locks, id);
Ok(setup(&db.lock_all(locks).await?)?)
}
pub fn setup(
locks: &mut Vec<LockTargetId>,
id: &PackageId,
) -> impl FnOnce(&Verifier) -> Result<Self, Error> {
let config = ConfigReceipts::setup(locks);
let removing = crate::db::DatabaseModel::new()
.package_data()
.idx_model(id)
.and_then(|pde| pde.removing())
.make_locker(LockType::Write)
.add_to_keys(locks);
let current_dependents = crate::db::DatabaseModel::new()
.package_data()
.star()
.installed()
.map(|x| x.current_dependents())
.make_locker(LockType::Write)
.add_to_keys(locks);
let packages = crate::db::DatabaseModel::new()
.package_data()
.make_locker(LockType::Write)
.add_to_keys(locks);
let update_depenency_receipts = UpdateDependencyReceipts::setup(locks);
move |skeleton_key| {
Ok(Self {
config: config(skeleton_key)?,
removing: removing.verify(skeleton_key)?,
current_dependents: current_dependents.verify(skeleton_key)?,
update_depenency_receipts: update_depenency_receipts(skeleton_key)?,
packages: packages.verify(skeleton_key)?,
})
}
}
}
#[instrument(skip(ctx, secrets, db))]
pub async fn uninstall<Ex>(
ctx: &RpcContext,
@@ -245,37 +339,24 @@ where
for<'a> &'a mut Ex: Executor<'a, Database = Sqlite>,
{
let mut tx = db.begin().await?;
crate::db::DatabaseModel::new()
.package_data()
.lock(&mut tx, LockType::Write)
.await?;
let entry = crate::db::DatabaseModel::new()
.package_data()
.idx_model(id)
.and_then(|pde| pde.removing())
.get(&mut tx, true)
.await?
.into_owned()
.ok_or_else(|| {
Error::new(
eyre!("Package not in removing state: {}", id),
crate::ErrorKind::NotFound,
)
})?;
let receipts = UninstallReceipts::new(&mut tx, id).await?;
let entry = receipts.removing.get(&mut tx).await?;
cleanup(ctx, &entry.manifest.id, &entry.manifest.version).await?;
crate::db::DatabaseModel::new()
.package_data()
.remove(&mut tx, id)
.await?;
let packages = {
let mut packages = receipts.packages.get(&mut tx).await?;
packages.0.remove(id);
packages
};
receipts.packages.set(&mut tx, packages).await?;
// once we have removed the package entry, we can change all the dependent pointers to null
reconfigure_dependents_with_live_pointers(ctx, &mut tx, &entry).await?;
reconfigure_dependents_with_live_pointers(ctx, &mut tx, &receipts.config, &entry).await?;
remove_from_current_dependents_lists(
&mut tx,
&entry.manifest.id,
entry.current_dependencies.keys(),
&receipts.current_dependents,
)
.await?;
update_dependency_errors_of_dependents(
@@ -283,6 +364,7 @@ where
&mut tx,
&entry.manifest.id,
entry.current_dependents.keys(),
&receipts.update_depenency_receipts,
)
.await?;
let volumes = ctx

View File

@@ -14,7 +14,7 @@ use futures::{FutureExt, StreamExt, TryStreamExt};
use http::header::CONTENT_LENGTH;
use http::{Request, Response, StatusCode};
use hyper::Body;
use patch_db::{DbHandle, LockType};
use patch_db::{DbHandle, LockReceipt, LockType};
use reqwest::Url;
use rpc_toolkit::yajrc::RpcError;
use rpc_toolkit::{command, Context};
@@ -25,8 +25,6 @@ use tokio_stream::wrappers::ReadDirStream;
use tracing::instrument;
use self::cleanup::{cleanup_failed, remove_from_current_dependents_lists};
use crate::context::{CliContext, RpcContext};
use crate::core::rpc_continuations::{RequestGuid, RpcContinuation};
use crate::db::model::{
CurrentDependencyInfo, InstalledPackageDataEntry, PackageDataEntry, RecoveredPackageInfo,
StaticDependencyInfo, StaticFiles,
@@ -47,16 +45,24 @@ use crate::util::serde::{display_serializable, IoFormat, Port};
use crate::util::{display_none, AsyncFileExt, Version};
use crate::version::{Current, VersionT};
use crate::volume::asset_dir;
use crate::{
config::ConfigReceipts,
context::{CliContext, RpcContext},
};
use crate::{
core::rpc_continuations::{RequestGuid, RpcContinuation},
dependencies::BreakTransitiveReceipts,
};
use crate::{Error, ErrorKind, ResultExt};
pub mod cleanup;
pub mod progress;
pub mod update;
pub const PKG_ARCHIVE_DIR: &'static str = "package-data/archive";
pub const PKG_PUBLIC_DIR: &'static str = "package-data/public";
pub const PKG_DOCKER_DIR: &'static str = "package-data/docker";
pub const PKG_WASM_DIR: &'static str = "package-data/wasm";
pub const PKG_ARCHIVE_DIR: &str = "package-data/archive";
pub const PKG_PUBLIC_DIR: &str = "package-data/public";
pub const PKG_DOCKER_DIR: &str = "package-data/docker";
pub const PKG_WASM_DIR: &str = "package-data/wasm";
#[command(display(display_serializable))]
pub async fn list(#[context] ctx: RpcContext) -> Result<Vec<(PackageId, Version)>, Error> {
@@ -447,7 +453,7 @@ pub async fn sideload(
});
let cont = RpcContinuation {
created_at: Instant::now(), // TODO
handler: handler,
handler,
};
// gc the map
let mut guard = ctx.rpc_stream_continuations.lock().await;
@@ -562,8 +568,15 @@ pub async fn uninstall_dry(
let mut db = ctx.db.handle();
let mut tx = db.begin().await?;
let mut breakages = BTreeMap::new();
break_all_dependents_transitive(&mut tx, &id, DependencyError::NotInstalled, &mut breakages)
.await?;
let receipts = BreakTransitiveReceipts::new(&mut tx).await?;
break_all_dependents_transitive(
&mut tx,
&id,
DependencyError::NotInstalled,
&mut breakages,
&receipts,
)
.await?;
tx.abort().await?;
@@ -678,6 +691,35 @@ pub async fn delete_recovered(
})
}
pub struct DownloadInstallReceipts {
package_receipts: crate::db::package::PackageReceipts,
manifest_receipts: crate::db::package::ManifestReceipts,
}
impl DownloadInstallReceipts {
pub async fn new<'a>(db: &'a mut impl DbHandle, id: &PackageId) -> Result<Self, Error> {
let mut locks = Vec::new();
let setup = Self::setup(&mut locks, id);
Ok(setup(&db.lock_all(locks).await?)?)
}
pub fn setup(
locks: &mut Vec<patch_db::LockTargetId>,
id: &PackageId,
) -> impl FnOnce(&patch_db::Verifier) -> Result<Self, Error> {
let package_receipts = crate::db::package::PackageReceipts::setup(locks);
let manifest_receipts = crate::db::package::ManifestReceipts::setup(locks, id);
move |skeleton_key| {
Ok(Self {
package_receipts: package_receipts(skeleton_key)?,
manifest_receipts: manifest_receipts(skeleton_key)?,
})
}
}
}
#[instrument(skip(ctx, temp_manifest, s9pk))]
pub async fn download_install_s9pk(
ctx: &RpcContext,
@@ -692,14 +734,14 @@ pub async fn download_install_s9pk(
if let Err(e) = async {
let mut db_handle = ctx.db.handle();
let mut tx = db_handle.begin().await?;
let receipts = DownloadInstallReceipts::new(&mut tx, &pkg_id).await?;
// Build set of existing manifests
let mut manifests = Vec::new();
for pkg in crate::db::package::get_packages(&mut tx).await? {
match crate::db::package::get_manifest(&mut tx, &pkg).await? {
Some(m) => {
manifests.push(m);
}
None => {}
for pkg in crate::db::package::get_packages(&mut tx, &receipts.package_receipts).await? {
if let Some(m) =
crate::db::package::get_manifest(&mut tx, &pkg, &receipts.manifest_receipts).await?
{
manifests.push(m);
}
}
// Build map of current port -> ssl mappings
@@ -732,6 +774,7 @@ pub async fn download_install_s9pk(
}
}
}
drop(receipts);
tx.save().await?;
drop(db_handle);
@@ -792,8 +835,9 @@ pub async fn download_install_s9pk(
{
let mut handle = ctx.db.handle();
let mut tx = handle.begin().await?;
let receipts = cleanup::CleanupFailedReceipts::new(&mut tx).await?;
if let Err(e) = cleanup_failed(&ctx, &mut tx, pkg_id).await {
if let Err(e) = cleanup_failed(&ctx, &mut tx, pkg_id, &receipts).await {
tracing::error!("Failed to clean up {}@{}: {}", pkg_id, version, e);
tracing::debug!("{:?}", e);
} else {
@@ -805,6 +849,39 @@ pub async fn download_install_s9pk(
}
}
pub struct InstallS9Receipts {
config: ConfigReceipts,
recovered_packages: LockReceipt<BTreeMap<PackageId, RecoveredPackageInfo>, ()>,
}
impl InstallS9Receipts {
pub async fn new<'a>(db: &'a mut impl DbHandle) -> Result<Self, Error> {
let mut locks = Vec::new();
let setup = Self::setup(&mut locks);
Ok(setup(&db.lock_all(locks).await?)?)
}
pub fn setup(
locks: &mut Vec<patch_db::LockTargetId>,
) -> impl FnOnce(&patch_db::Verifier) -> Result<Self, Error> {
let config = ConfigReceipts::setup(locks);
let recovered_packages = crate::db::DatabaseModel::new()
.recovered_packages()
.make_locker(LockType::Write)
.add_to_keys(locks);
move |skeleton_key| {
Ok(Self {
config: config(skeleton_key)?,
recovered_packages: recovered_packages.verify(skeleton_key)?,
})
}
}
}
#[instrument(skip(ctx, rdr))]
pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
ctx: &RpcContext,
@@ -1183,6 +1260,8 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
},
);
pde.save(&mut tx).await?;
let receipts = InstallS9Receipts::new(&mut tx).await?;
// UpdateDependencyReceipts
let mut dep_errs = model
.expect(&mut tx)
.await?
@@ -1193,7 +1272,14 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
.dependency_errors()
.get_mut(&mut tx)
.await?;
*dep_errs = DependencyErrors::init(ctx, &mut tx, &manifest, &current_dependencies).await?;
*dep_errs = DependencyErrors::init(
ctx,
&mut tx,
&manifest,
&current_dependencies,
&receipts.config.try_heal_receipts,
)
.await?;
dep_errs.save(&mut tx).await?;
if let PackageDataEntry::Updating {
@@ -1244,6 +1330,7 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
false,
&mut BTreeMap::new(),
&mut BTreeMap::new(),
&receipts.config,
)
.await?;
let mut main_status = crate::db::DatabaseModel::new()
@@ -1261,9 +1348,20 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
*main_status = prev.status.main;
main_status.save(&mut tx).await?;
}
remove_from_current_dependents_lists(&mut tx, pkg_id, prev.current_dependencies.keys())
.await?; // remove previous
add_dependent_to_current_dependents_lists(&mut tx, pkg_id, &current_dependencies).await?; // add new
remove_from_current_dependents_lists(
&mut tx,
pkg_id,
prev.current_dependencies.keys(),
&receipts.config.current_dependents,
)
.await?; // remove previous
add_dependent_to_current_dependents_lists(
&mut tx,
pkg_id,
&current_dependencies,
&receipts.config.current_dependents,
)
.await?; // add new
update_dependency_errors_of_dependents(
ctx,
&mut tx,
@@ -1272,6 +1370,7 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
.keys()
.chain(prev.current_dependents.keys())
.collect::<BTreeSet<_>>(),
&receipts.config.update_dependency_receipts,
)
.await?;
if &prev.manifest.version != version {
@@ -1290,39 +1389,84 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
&manifest.volumes,
)
.await?;
add_dependent_to_current_dependents_lists(&mut tx, pkg_id, &current_dependencies).await?;
update_dependency_errors_of_dependents(ctx, &mut tx, pkg_id, current_dependents.keys())
.await?;
add_dependent_to_current_dependents_lists(
&mut tx,
pkg_id,
&current_dependencies,
&receipts.config.current_dependents,
)
.await?;
update_dependency_errors_of_dependents(
ctx,
&mut tx,
pkg_id,
current_dependents.keys(),
&receipts.config.update_dependency_receipts,
)
.await?;
} else if let Some(recovered) = {
// solve taxonomy escalation
crate::db::DatabaseModel::new()
.recovered_packages()
.lock(&mut tx, LockType::Write)
.await?;
crate::db::DatabaseModel::new()
.recovered_packages()
.idx_model(pkg_id)
.get(&mut tx, true)
receipts
.recovered_packages
.get(&mut tx)
.await?
.into_owned()
.remove(pkg_id)
} {
handle_recovered_package(recovered, manifest, ctx, pkg_id, version, &mut tx).await?;
add_dependent_to_current_dependents_lists(&mut tx, pkg_id, &current_dependencies).await?;
update_dependency_errors_of_dependents(ctx, &mut tx, pkg_id, current_dependents.keys())
.await?;
handle_recovered_package(
recovered,
manifest,
ctx,
pkg_id,
version,
&mut tx,
&receipts.config,
)
.await?;
add_dependent_to_current_dependents_lists(
&mut tx,
pkg_id,
&current_dependencies,
&receipts.config.current_dependents,
)
.await?;
update_dependency_errors_of_dependents(
ctx,
&mut tx,
pkg_id,
current_dependents.keys(),
&receipts.config.update_dependency_receipts,
)
.await?;
} else {
add_dependent_to_current_dependents_lists(&mut tx, pkg_id, &current_dependencies).await?;
update_dependency_errors_of_dependents(ctx, &mut tx, pkg_id, current_dependents.keys())
.await?;
add_dependent_to_current_dependents_lists(
&mut tx,
pkg_id,
&current_dependencies,
&receipts.config.current_dependents,
)
.await?;
update_dependency_errors_of_dependents(
ctx,
&mut tx,
pkg_id,
current_dependents.keys(),
&receipts.config.update_dependency_receipts,
)
.await?;
}
crate::db::DatabaseModel::new()
.recovered_packages()
.remove(&mut tx, pkg_id)
let recovered_packages = {
let mut r = receipts.recovered_packages.get(&mut tx).await?;
r.remove(pkg_id);
r
};
receipts
.recovered_packages
.set(&mut tx, recovered_packages)
.await?;
if let Some(installed) = pde.installed() {
reconfigure_dependents_with_live_pointers(ctx, &mut tx, installed).await?;
reconfigure_dependents_with_live_pointers(ctx, &mut tx, &receipts.config, installed)
.await?;
}
sql_tx.commit().await?;
@@ -1333,7 +1477,7 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
Ok(())
}
#[instrument(skip(ctx, tx))]
#[instrument(skip(ctx, tx, receipts))]
async fn handle_recovered_package(
recovered: RecoveredPackageInfo,
manifest: Manifest,
@@ -1341,6 +1485,7 @@ async fn handle_recovered_package(
pkg_id: &PackageId,
version: &Version,
tx: &mut patch_db::Transaction<&mut patch_db::PatchDbHandle>,
receipts: &ConfigReceipts,
) -> Result<(), Error> {
let configured = if let Some(migration) =
manifest
@@ -1361,6 +1506,7 @@ async fn handle_recovered_package(
false,
&mut BTreeMap::new(),
&mut BTreeMap::new(),
&receipts,
)
.await?;
}

View File

@@ -24,10 +24,12 @@ pub async fn dry(
let mut db = ctx.db.handle();
let mut tx = db.begin().await?;
let mut breakages = BTreeMap::new();
let receipts = crate::dependencies::BreakTransitiveReceipts::new(&mut tx).await?;
crate::db::DatabaseModel::new()
.package_data()
.lock(&mut tx, LockType::Read)
.await?;
for dependent in crate::db::DatabaseModel::new()
.package_data()
.idx_model(&id)
@@ -65,6 +67,7 @@ pub async fn dry(
received: version.clone(),
},
&mut breakages,
&receipts,
)
.await?;
}