diff options
-rw-r--r-- | Cargo.lock | 108 | ||||
-rw-r--r-- | yt/Cargo.toml | 1 | ||||
-rw-r--r-- | yt/src/download/mod.rs | 9 | ||||
-rw-r--r-- | yt/src/storage/video_database/mod.rs | 1 | ||||
-rw-r--r-- | yt/src/storage/video_database/notify.rs | 67 |
5 files changed, 182 insertions, 4 deletions
diff --git a/Cargo.lock b/Cargo.lock index 06a7253..ce5e368 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -554,6 +554,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] +name = "filetime" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" +dependencies = [ + "cfg-if", + "libc", + "libredox", + "windows-sys 0.59.0", +] + +[[package]] name = "flume" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -968,6 +980,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" [[package]] +name = "inotify" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" +dependencies = [ + "bitflags 2.8.0", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + +[[package]] name = "is-terminal" version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1010,6 +1042,26 @@ dependencies = [ ] [[package]] +name = "kqueue" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" +dependencies = [ + "bitflags 1.3.2", + "libc", +] + +[[package]] name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1058,6 +1110,17 @@ dependencies = [ ] [[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.8.0", + "libc", + "redox_syscall", +] + +[[package]] name = "libsqlite3-sys" version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1143,6 +1206,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", + "log", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.52.0", ] @@ -1158,6 +1222,30 @@ dependencies = [ ] [[package]] +name = "notify" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fee8403b3d66ac7b26aee6e40a897d85dc5ce26f44da36b8b73e987cc52e943" +dependencies = [ + "bitflags 2.8.0", + "filetime", + "inotify", + "kqueue", + "libc", + "log", + "mio", + "notify-types", + "walkdir", + "windows-sys 0.59.0", +] + +[[package]] +name = "notify-types" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d" + +[[package]] name = "nucleo-matcher" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1595,6 +1683,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" [[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2341,6 +2438,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2690,6 +2797,7 @@ dependencies = [ "futures", "libmpv2", "log", + "notify", "nucleo-matcher", "owo-colors", "regex", diff --git a/yt/Cargo.toml b/yt/Cargo.toml index ae3d229..2a93f40 100644 --- a/yt/Cargo.toml +++ b/yt/Cargo.toml @@ -48,6 +48,7 @@ url.workspace = true yt_dlp.workspace = true termsize.workspace = true uu_fmt.workspace = true +notify = { version = "8.0.0", default-features = false } [[bin]] name = "yt" diff --git a/yt/src/download/mod.rs b/yt/src/download/mod.rs index 7cfa0b0..317f636 100644 --- a/yt/src/download/mod.rs +++ b/yt/src/download/mod.rs @@ -18,6 +18,7 @@ use crate::{ downloader::{get_next_uncached_video, set_video_cache_path}, extractor_hash::ExtractorHash, getters::get_video_yt_dlp_opts, + notify::wait_for_cache_reduction, }, unreachable::Unreachable, }; @@ -160,12 +161,10 @@ impl Downloader { "The `printed_warning` should be false in this case, \ and thus should have already set the `cached_cache_allocation`." ); - // info!("Current cache size allocation: '{}'", cache_allocation); - // self.cached_cache_allocation = Some(cache_allocation); } // Wait and hope, that a large video is deleted from the cache. - time::sleep(Duration::from_secs(10)).await; + wait_for_cache_reduction(app).await?; Ok(CacheSizeCheck::TooLarge) } else { self.printed_warning = false; @@ -210,6 +209,7 @@ impl Downloader { ); // Replace the currently downloading video + // FIXME(@bpeetz): This does not work (probably because of the python part.) <2025-02-21> current_download.task_handle.abort(); let new_current_download = @@ -227,7 +227,8 @@ impl Downloader { self.current_download = Some(new_current_download); } - time::sleep(Duration::new(1, 0)).await; + // TODO(@bpeetz): Why do we sleep here? <2025-02-21> + time::sleep(Duration::from_secs(1)).await; } info!("Finished downloading!"); diff --git a/yt/src/storage/video_database/mod.rs b/yt/src/storage/video_database/mod.rs index afcd179..22628b5 100644 --- a/yt/src/storage/video_database/mod.rs +++ b/yt/src/storage/video_database/mod.rs @@ -18,6 +18,7 @@ pub mod downloader; pub mod extractor_hash; pub mod getters; pub mod setters; +pub mod notify; #[derive(Debug, Clone)] pub struct Video { diff --git a/yt/src/storage/video_database/notify.rs b/yt/src/storage/video_database/notify.rs new file mode 100644 index 0000000..56599ba --- /dev/null +++ b/yt/src/storage/video_database/notify.rs @@ -0,0 +1,67 @@ +use std::{ + path::{Path, PathBuf}, + sync::mpsc, + thread::sleep, + time::Duration, +}; + +use crate::app::App; + +use anyhow::{Context, Result}; +use notify::{ + Event, EventKind, RecursiveMode, Watcher, + event::{DataChange, ModifyKind}, +}; +use tokio::task; + +/// This functions registers a watcher for the database and only returns once a write was +/// registered for the database. +pub async fn wait_for_db_write(app: &App) -> Result<()> { + let db_path: PathBuf = app.config.paths.database_path.clone(); + task::spawn_blocking(move || wait_for_db_write_sync(&db_path)).await? +} + +fn wait_for_db_write_sync(db_path: &Path) -> Result<()> { + let (tx, rx) = mpsc::channel::<notify::Result<Event>>(); + + let mut watcher = notify::recommended_watcher(tx)?; + + watcher.watch(db_path, RecursiveMode::NonRecursive)?; + + for res in rx { + let event = res.context("Failed to wait for db write")?; + + if let EventKind::Modify(ModifyKind::Data(DataChange::Any)) = event.kind { + // Buffer some of the `Modify` event burst. + sleep(Duration::from_millis(10)); + + return Ok(()); + } + } + + Ok(()) +} + +/// This functions registers a watcher for the cache path and returns once a file was removed +pub async fn wait_for_cache_reduction(app: &App) -> Result<()> { + let download_directory: PathBuf = app.config.paths.download_dir.clone(); + task::spawn_blocking(move || wait_for_cache_reduction_sync(&download_directory)).await? +} + +fn wait_for_cache_reduction_sync(download_directory: &Path) -> Result<()> { + let (tx, rx) = mpsc::channel::<notify::Result<Event>>(); + + let mut watcher = notify::recommended_watcher(tx)?; + + watcher.watch(download_directory, RecursiveMode::Recursive)?; + + for res in rx { + let event = res.context("Failed to wait for cache size reduction")?; + + if let EventKind::Remove(_) = event.kind { + return Ok(()); + } + } + + Ok(()) +} |