use geekorm::{ConnectionManager, prelude::*};
use super::TaskTrait;
use crate::{
models::{Component, ComponentType, SnapshotMetadataKey},
utils::catalogue::Catalogue,
};
#[derive(Default)]
pub struct CatalogueTask {
force: bool,
snapshot: Option<i32>,
}
#[async_trait::async_trait]
impl TaskTrait for CatalogueTask {
async fn run(&self, database: &ConnectionManager) -> Result<(), crate::KonarrError> {
log::info!("Starting Catalogue Task");
let catalogue = Catalogue::new();
let mut counter = 0;
let mut comps = Component::all(&database.acquire().await).await?;
log::debug!("Checking component types for `{}` Components", comps.len());
for mut comp in comps.iter_mut() {
if !self.force {
match comp.component_type {
ComponentType::Unknown
| ComponentType::Library
| ComponentType::Application => {
if catalogue.catalogue(&mut comp)? {
log::info!("Updating component_type: {}", comp.component_type);
comp.update(&database.acquire().await).await?;
counter += 1;
}
}
_ => {}
}
} else if self.force && catalogue.catalogue(&mut comp)? {
log::info!("Updating component_type: {}", comp.component_type);
comp.update(&database.acquire().await).await?;
counter += 1;
}
}
if counter != 0 {
log::info!("Updated `{}` component out of `{}`", counter, comps.len());
}
if let Some(snapshot) = self.snapshot {
process_snapshot(database, snapshot).await?;
}
log::info!("Catalogue Task Completed");
Ok(())
}
}
impl CatalogueTask {
pub fn force() -> Self {
Self {
force: true,
snapshot: None,
}
}
pub fn snapshot(id: impl Into<i32>) -> Self {
Self {
force: false,
snapshot: Some(id.into()),
}
}
}
async fn process_snapshot(
database: &ConnectionManager,
snapshot_id: i32,
) -> Result<(), crate::KonarrError> {
log::info!("Processing catalogue Snapshot ID: {}", snapshot_id);
let mut snapshot =
crate::models::Snapshot::fetch_by_primary_key(&database.acquire().await, snapshot_id)
.await?;
let dependencies = snapshot
.fetch_all_dependencies(&database.acquire().await)
.await?;
for dependency in dependencies {
let comp = dependency.component();
match comp.component_type {
ComponentType::OperatingSystem => {
snapshot
.set_metadata(
&database.acquire().await,
SnapshotMetadataKey::Os,
&dependency.name(),
)
.await?;
if let Some(version) = dependency.version() {
snapshot
.set_metadata(
&database.acquire().await,
SnapshotMetadataKey::OsVersion,
&version,
)
.await?;
}
}
_ => {}
}
}
Ok(())
}