diff options
Diffstat (limited to 'server/src/import.rs')
-rw-r--r-- | server/src/import.rs | 43 |
1 files changed, 26 insertions, 17 deletions
diff --git a/server/src/import.rs b/server/src/import.rs index c8f4f10..b306332 100644 --- a/server/src/import.rs +++ b/server/src/import.rs @@ -5,27 +5,38 @@ */ use crate::{database::Database, CONF}; use anyhow::{bail, Context, Ok}; +use async_recursion::async_recursion; use jellycommon::Node; use log::info; -use std::{ffi::OsStr, fs::File, os::unix::prelude::OsStrExt, path::PathBuf}; +use std::{ffi::OsStr, fs::File, os::unix::prelude::OsStrExt, path::PathBuf, sync::LazyLock}; +use tokio::sync::Semaphore; -pub fn import(db: &Database) -> anyhow::Result<()> { +static IMPORT_SEM: LazyLock<Semaphore> = LazyLock::new(|| Semaphore::new(1)); + +pub async fn import(db: &Database) -> anyhow::Result<()> { info!("clearing node tree"); - db.node.clear()?; - info!("importing..."); - import_path(CONF.library_path.clone(), db, None).context("indexing")?; + let permit = IMPORT_SEM.try_acquire()?; + { + db.node.clear()?; + info!("importing..."); + import_path(CONF.library_path.clone(), db, None) + .await + .context("indexing")?; + info!("import completed"); + } + drop(permit); Ok(()) } -pub fn import_path( +#[async_recursion] +pub async fn import_path( path: PathBuf, db: &Database, parent: Option<String>, ) -> anyhow::Result<Vec<String>> { if path.is_dir() { let mpath = path.join("directory.json"); - let children = path.read_dir()?.filter_map(|e| { - let e = e.unwrap(); + let children_paths = path.read_dir()?.map(Result::unwrap).filter_map(|e| { if e.path().extension() == Some(&OsStr::from_bytes(b"jelly")) || e.metadata().unwrap().is_dir() { @@ -35,23 +46,21 @@ pub fn import_path( } }); let identifier = path.file_name().unwrap().to_str().unwrap().to_string(); - let children = children - .map(|e| import_path(e, db, Some(identifier.clone()))) - .collect::<anyhow::Result<Vec<_>>>()? - .into_iter() - .flatten() - .collect(); + let mut children_ids = Vec::new(); + for p in children_paths { + children_ids.extend(import_path(p, db, Some(identifier.clone())).await?) + } if mpath.exists() { let mut data: Node = serde_json::from_reader(File::open(mpath).context("metadata missing")?)?; - data.public.children = children; + data.public.children = children_ids; data.public.parent = parent; info!("insert {identifier}"); db.node.insert(&identifier, &data)?; Ok(vec![identifier]) } else { - Ok(children) + Ok(children_ids) } } else if path.is_file() { info!("loading item {path:?}"); @@ -65,7 +74,7 @@ pub fn import_path( .strip_suffix(".jelly") .unwrap() .to_string(); - + info!("insert {identifier}"); data.public.parent = parent; db.node.insert(&identifier, &data)?; |