config changes; cleanup wip

This commit is contained in:
Aiden McClelland
2021-08-19 13:12:02 -06:00
committed by Aiden McClelland
parent 6c7dc71ed4
commit 0aa75ee008
5 changed files with 149 additions and 58 deletions

View File

@@ -17,7 +17,9 @@ use crate::config::spec::PackagePointerSpecVariant;
use crate::context::{EitherContext, ExtendedContext}; use crate::context::{EitherContext, ExtendedContext};
use crate::db::model::{CurrentDependencyInfo, InstalledPackageDataEntryModel}; use crate::db::model::{CurrentDependencyInfo, InstalledPackageDataEntryModel};
use crate::db::util::WithRevision; use crate::db::util::WithRevision;
use crate::dependencies::{BreakageRes, DependencyError, TaggedDependencyError}; use crate::dependencies::{
update_current_dependents, BreakageRes, DependencyError, TaggedDependencyError,
};
use crate::s9pk::manifest::PackageId; use crate::s9pk::manifest::PackageId;
use crate::util::{ use crate::util::{
display_none, display_serializable, parse_duration, parse_stdin_deserializable, IoFormat, display_none, display_serializable, parse_duration, parse_stdin_deserializable, IoFormat,
@@ -396,21 +398,7 @@ pub fn configure<'a, Db: DbHandle>(
}; };
// update dependencies // update dependencies
for (dependency, dep_info) in current_dependencies { update_current_dependents(db, id, &current_dependencies).await?;
if let Some(dependency_model) = crate::db::DatabaseModel::new()
.package_data()
.idx_model(&dependency)
.and_then(|pkg| pkg.installed())
.check(db)
.await?
{
dependency_model
.current_dependents()
.idx_model(id)
.put(db, &dep_info)
.await?;
}
}
// cache current config for dependents // cache current config for dependents
overrides.insert(id.clone(), config.clone()); overrides.insert(id.clone(), config.clone());

View File

@@ -245,7 +245,7 @@ pub struct WithDescription<T> {
pub description: Option<String>, pub description: Option<String>,
pub name: String, pub name: String,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub change_warning: Option<String>, pub warning: Option<String>,
} }
#[async_trait] #[async_trait]
impl<T> ValueSpec for WithDescription<T> impl<T> ValueSpec for WithDescription<T>
@@ -318,7 +318,7 @@ pub enum ValueSpecAny {
Enum(WithDescription<WithDefault<ValueSpecEnum>>), Enum(WithDescription<WithDefault<ValueSpecEnum>>),
List(ValueSpecList), List(ValueSpecList),
Number(WithDescription<WithDefault<WithNullable<ValueSpecNumber>>>), Number(WithDescription<WithDefault<WithNullable<ValueSpecNumber>>>),
Object(WithDescription<WithNullable<ValueSpecObject>>), Object(WithDescription<ValueSpecObject>),
String(WithDescription<WithDefault<WithNullable<ValueSpecString>>>), String(WithDescription<WithDefault<WithNullable<ValueSpecString>>>),
Union(WithDescription<WithDefault<ValueSpecUnion>>), Union(WithDescription<WithDefault<ValueSpecUnion>>),
Pointer(WithDescription<ValueSpecPointer>), Pointer(WithDescription<ValueSpecPointer>),
@@ -947,8 +947,6 @@ impl DefaultableWith for ValueSpecNumber {
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
pub struct ValueSpecObject { pub struct ValueSpecObject {
pub spec: ConfigSpec, pub spec: ConfigSpec,
#[serde(default)]
pub null_by_default: bool,
pub display_as: Option<String>, pub display_as: Option<String>,
#[serde(default)] #[serde(default)]
pub unique_by: UniqueBy, pub unique_by: UniqueBy,
@@ -1016,11 +1014,7 @@ impl DefaultableWith for ValueSpecObject {
_rng: &mut R, _rng: &mut R,
_timeout: &Option<Duration>, _timeout: &Option<Duration>,
) -> Result<Value, Self::Error> { ) -> Result<Value, Self::Error> {
if self.null_by_default { Ok(Value::Object(spec.clone()))
Ok(Value::Null)
} else {
Ok(Value::Object(spec.clone()))
}
} }
} }
impl Defaultable for ValueSpecObject { impl Defaultable for ValueSpecObject {
@@ -1031,11 +1025,7 @@ impl Defaultable for ValueSpecObject {
rng: &mut R, rng: &mut R,
timeout: &Option<Duration>, timeout: &Option<Duration>,
) -> Result<Value, Self::Error> { ) -> Result<Value, Self::Error> {
if self.null_by_default { self.spec.gen(rng, timeout).map(Value::Object)
Ok(Value::Null)
} else {
self.spec.gen(rng, timeout).map(Value::Object)
}
} }
} }

View File

@@ -8,6 +8,7 @@ use serde::{Deserialize, Serialize};
use crate::action::ActionImplementation; use crate::action::ActionImplementation;
use crate::config::{Config, ConfigSpec}; use crate::config::{Config, ConfigSpec};
use crate::db::model::CurrentDependencyInfo;
use crate::net::interface::InterfaceId; use crate::net::interface::InterfaceId;
use crate::s9pk::manifest::PackageId; use crate::s9pk::manifest::PackageId;
use crate::status::health_check::{HealthCheckId, HealthCheckResult, HealthCheckResultVariant}; use crate::status::health_check::{HealthCheckId, HealthCheckResult, HealthCheckResultVariant};
@@ -254,3 +255,26 @@ impl DependencyConfig {
.map_err(|e| Error::new(anyhow!("{}", e.1), crate::ErrorKind::AutoConfigure)) .map_err(|e| Error::new(anyhow!("{}", e.1), crate::ErrorKind::AutoConfigure))
} }
} }
pub async fn update_current_dependents<Db: DbHandle>(
db: &mut Db,
dependent_id: &PackageId,
current_dependencies: &IndexMap<PackageId, CurrentDependencyInfo>,
) -> Result<(), Error> {
for (dependency, dep_info) in current_dependencies {
if let Some(dependency_model) = crate::db::DatabaseModel::new()
.package_data()
.idx_model(&dependency)
.and_then(|pkg| pkg.installed())
.check(db)
.await?
{
dependency_model
.current_dependents()
.idx_model(dependent_id)
.put(db, &dep_info)
.await?;
}
}
Ok(())
}

View File

@@ -1,7 +1,73 @@
use std::borrow::Cow;
use anyhow::anyhow;
use patch_db::DbHandle;
use crate::db::model::InstalledPackageDataEntry; use crate::db::model::InstalledPackageDataEntry;
use crate::dependencies::DependencyError;
use crate::s9pk::manifest::{Manifest, PackageId}; use crate::s9pk::manifest::{Manifest, PackageId};
use crate::util::Version;
use crate::Error; use crate::Error;
pub async fn cleanup(info: Result<InstalledPackageDataEntry, &Manifest>) -> Result<(), Error> { pub async fn update_dependents<'a, Db: DbHandle, I: IntoIterator<Item = &'a PackageId>>(
db: &mut Db,
id: &PackageId,
deps: I,
) -> Result<(), Error> {
for dep in deps {
let man = crate::db::DatabaseModel::new()
.package_data()
.idx_model(&dep)
.expect(db)
.await?
.installed()
.expect(db)
.await?
.manifest()
.get(db, true)
.await?;
if let Err(e) = man
.dependencies
.0
.get(id)
.ok_or_else(|| {
Error::new(
anyhow!("missing dependency info"),
crate::ErrorKind::Database,
)
})?
.satisfied(db, id, None, dep, &man.version, &man.volumes)
.await?
{
let mut errs = crate::db::DatabaseModel::new()
.package_data()
.idx_model(&dep)
.expect(db)
.await?
.installed()
.expect(db)
.await?
.status()
.dependency_errors()
.get_mut(db)
.await?;
errs.0.insert(id.clone(), e);
errs.save(db).await?;
}
}
Ok(())
}
pub async fn cleanup<Db: DbHandle>(
db: &mut Db,
info: Result<InstalledPackageDataEntry, &Manifest>,
) -> Result<(), Error> {
let man = match info {
Ok(pde) => {
todo!();
Cow::Owned(pde.manifest)
}
Err(man) => Cow::Borrowed(man),
};
Ok(()) // TODO Ok(()) // TODO
} }

View File

@@ -1,3 +1,4 @@
use std::collections::HashSet;
use std::fmt::Display; use std::fmt::Display;
use std::io::SeekFrom; use std::io::SeekFrom;
use std::path::Path; use std::path::Path;
@@ -32,6 +33,8 @@ use crate::db::model::{
CurrentDependencyInfo, InstalledPackageDataEntry, PackageDataEntry, StaticDependencyInfo, CurrentDependencyInfo, InstalledPackageDataEntry, PackageDataEntry, StaticDependencyInfo,
StaticFiles, StaticFiles,
}; };
use crate::dependencies::update_current_dependents;
use crate::install::cleanup::update_dependents;
use crate::s9pk::manifest::{Manifest, PackageId}; use crate::s9pk::manifest::{Manifest, PackageId};
use crate::s9pk::reader::S9pkReader; use crate::s9pk::reader::S9pkReader;
use crate::status::{DependencyErrors, MainStatus, Status}; use crate::status::{DependencyErrors, MainStatus, Status};
@@ -234,8 +237,14 @@ pub async fn download_install_s9pk(
.await; .await;
if let Err(e) = res { if let Err(e) = res {
if let Err(e) = cleanup(Err(temp_manifest)).await { let mut handle = ctx.db.handle();
let mut handle = ctx.db.handle(); if let Err(e) = cleanup(&mut handle, Err(temp_manifest)).await {
log::error!(
"Failed to clean up {}@{}: {}: Adding to broken packages",
pkg_id,
version,
e
);
let mut broken = crate::db::DatabaseModel::new() let mut broken = crate::db::DatabaseModel::new()
.broken_packages() .broken_packages()
.get_mut(&mut handle) .get_mut(&mut handle)
@@ -474,6 +483,31 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
} }
}) })
.collect(); .collect();
update_current_dependents(&mut tx, pkg_id, &current_dependencies).await?;
let current_dependents = {
// search required dependencies
let mut deps = IndexMap::new();
for package in crate::db::DatabaseModel::new()
.package_data()
.keys(&mut tx, true)
.await?
{
if let Some(dep) = crate::db::DatabaseModel::new()
.package_data()
.idx_model(&package)
.expect(&mut tx)
.await?
.installed()
.and_then(|i| i.current_dependencies().idx_model(pkg_id))
.get(&mut tx, true)
.await?
.to_owned()
{
deps.insert(package, dep);
}
}
deps
};
let installed = InstalledPackageDataEntry { let installed = InstalledPackageDataEntry {
status: Status { status: Status {
configured: manifest.config.is_none(), configured: manifest.config.is_none(),
@@ -484,30 +518,7 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
manifest: manifest.clone(), manifest: manifest.clone(),
system_pointers: Vec::new(), system_pointers: Vec::new(),
dependency_info, dependency_info,
current_dependents: { current_dependents: current_dependents.clone(),
// search required dependencies
let mut deps = IndexMap::new();
for package in crate::db::DatabaseModel::new()
.package_data()
.keys(&mut tx, true)
.await?
{
if let Some(dep) = crate::db::DatabaseModel::new()
.package_data()
.idx_model(&package)
.expect(&mut tx)
.await?
.installed()
.and_then(|i| i.current_dependencies().idx_model(pkg_id))
.get(&mut tx, true)
.await?
.to_owned()
{
deps.insert(package, dep);
}
}
deps
},
current_dependencies, current_dependencies,
interface_addresses, interface_addresses,
}; };
@@ -521,12 +532,22 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
}, },
); );
pde.save(&mut tx).await?; pde.save(&mut tx).await?;
if let PackageDataEntry::Updating { if let PackageDataEntry::Updating {
installed: prev, installed: prev,
manifest: prev_manifest, manifest: prev_manifest,
.. ..
} = prev } = prev
{ {
update_dependents(
&mut tx,
pkg_id,
current_dependents
.keys()
.chain(prev.current_dependents.keys())
.collect::<HashSet<_>>(),
)
.await?;
let mut configured = prev.status.configured; let mut configured = prev.status.configured;
if let Some(res) = prev_manifest if let Some(res) = prev_manifest
.migrations .migrations
@@ -540,7 +561,7 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
{ {
configured &= res.configured; configured &= res.configured;
} }
cleanup(Ok(prev)).await?; cleanup(&mut tx, Ok(prev)).await?;
if let Some(res) = manifest if let Some(res) = manifest
.migrations .migrations
.from(&prev_manifest.version, pkg_id, version, &manifest.volumes) .from(&prev_manifest.version, pkg_id, version, &manifest.volumes)
@@ -562,6 +583,8 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
.await?; .await?;
todo!("set as running if viable"); todo!("set as running if viable");
} }
} else {
update_dependents(&mut tx, pkg_id, current_dependents.keys()).await?;
} }
sql_tx.commit().await?; sql_tx.commit().await?;