Compare commits

..

2 Commits

4 changed files with 55 additions and 21 deletions

View File

@ -4,6 +4,9 @@ use sea_orm::{sea_query::IntoCondition, *};
use sea_query::{Alias, Expr, Query, SelectStatement}; use sea_query::{Alias, Expr, Query, SelectStatement};
use serde::Deserialize; use serde::Deserialize;
/// How many fields may be inserted at once into the database.
const PACKAGE_INSERT_LIMIT: usize = 1000;
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct Filter { pub struct Filter {
repo: Option<i32>, repo: Option<i32>,
@ -160,23 +163,34 @@ pub async fn insert(
.iter() .iter()
.map(|s| (PackageRelatedEnum::Optdepend, s)), .map(|s| (PackageRelatedEnum::Optdepend, s)),
); );
let related = crate::util::Chunked::new(related, PACKAGE_INSERT_LIMIT);
PackageRelated::insert_many(related.map(|(t, s)| package_related::ActiveModel { for chunk in related {
package_id: Set(pkg_entry.id), PackageRelated::insert_many(
r#type: Set(t), chunk
name: Set(s.to_string()), .into_iter()
})) .map(|(t, s)| package_related::ActiveModel {
.on_empty_do_nothing() package_id: Set(pkg_entry.id),
.exec(&txn) r#type: Set(t),
.await?; name: Set(s.to_string()),
}),
)
.on_empty_do_nothing()
.exec(&txn)
.await?;
}
PackageFile::insert_many(pkg.files.iter().map(|s| package_file::ActiveModel { let files = crate::util::Chunked::new(pkg.files, PACKAGE_INSERT_LIMIT);
package_id: Set(pkg_entry.id),
path: Set(s.display().to_string()), for chunk in files {
})) PackageFile::insert_many(chunk.into_iter().map(|s| package_file::ActiveModel {
.on_empty_do_nothing() package_id: Set(pkg_entry.id),
.exec(&txn) path: Set(s.display().to_string()),
.await?; }))
.on_empty_do_nothing()
.exec(&txn)
.await?;
}
txn.commit().await?; txn.commit().await?;

View File

@ -3,6 +3,7 @@ mod config;
pub mod db; pub mod db;
mod error; mod error;
mod repo; mod repo;
mod util;
mod web; mod web;
pub use config::{Config, DbConfig, FsConfig}; pub use config::{Config, DbConfig, FsConfig};

View File

@ -13,8 +13,6 @@ use libarchive::{
}; };
use sea_orm::ActiveValue::Set; use sea_orm::ActiveValue::Set;
const IGNORED_FILES: [&str; 5] = [".BUILDINFO", ".INSTALL", ".MTREE", ".PKGINFO", ".CHANGELOG"];
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Package { pub struct Package {
pub path: PathBuf, pub path: PathBuf,
@ -158,11 +156,9 @@ impl Package {
let entry = entry?; let entry = entry?;
let path_name = entry.pathname(); let path_name = entry.pathname();
if !IGNORED_FILES.iter().any(|p| p == &path_name) { if !path_name.starts_with('.') {
files.push(PathBuf::from(path_name)); files.push(PathBuf::from(path_name));
} } else if path_name == ".PKGINFO" {
if path_name == ".PKGINFO" {
info = Some(PkgInfo::parse(entry)?); info = Some(PkgInfo::parse(entry)?);
} }
} }

23
server/src/util.rs 100644
View File

@ -0,0 +1,23 @@
pub struct Chunked<I> {
iter: I,
chunk_size: usize,
}
impl<I: Iterator> Chunked<I> {
pub fn new<T: IntoIterator<IntoIter = I>>(into: T, chunk_size: usize) -> Self {
Self {
iter: into.into_iter(),
chunk_size,
}
}
}
// https://users.rust-lang.org/t/how-to-breakup-an-iterator-into-chunks/87915/5
impl<I: Iterator> Iterator for Chunked<I> {
type Item = Vec<I::Item>;
fn next(&mut self) -> Option<Self::Item> {
Some(self.iter.by_ref().take(self.chunk_size).collect())
.filter(|chunk: &Vec<_>| !chunk.is_empty())
}
}