aboutsummaryrefslogtreecommitdiffstats
path: root/src/download
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-08-25 15:48:54 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-08-25 15:48:54 +0200
commit09d03dc79c6e39f12392b3a9edf5c121519bfc92 (patch)
tree58b4d43f696a4e1de16bedb931677a577b81d3ea /src/download
parentdocs(cache): Add context to the cache_path deletion error (diff)
downloadyt-09d03dc79c6e39f12392b3a9edf5c121519bfc92.zip
fix(downloader): Be smarter, when checking for available cache
Diffstat (limited to 'src/download')
-rw-r--r--src/download/mod.rs98
1 files changed, 86 insertions, 12 deletions
diff --git a/src/download/mod.rs b/src/download/mod.rs
index d1de3ff..b29594f 100644
--- a/src/download/mod.rs
+++ b/src/download/mod.rs
@@ -53,9 +53,22 @@ impl CurrentDownload {
}
}
+enum CacheSizeCheck {
+ /// The video can be downloaded
+ Fits,
+
+ /// The video and the current cache size together would exceed the size
+ TooLarge,
+
+ /// The video would not even fit into the empty cache
+ ExceedsMaxCacheSize,
+}
+
pub struct Downloader {
current_download: Option<CurrentDownload>,
video_size_cache: HashMap<ExtractorHash, u64>,
+ printed_warning: bool,
+ cached_cache_allocation: Option<u64>,
}
impl Downloader {
@@ -63,6 +76,71 @@ impl Downloader {
Self {
current_download: None,
video_size_cache: HashMap::new(),
+ printed_warning: false,
+ cached_cache_allocation: None,
+ }
+ }
+
+ /// Check if enough cache is available. Will wait for 10s if it's not.
+ async fn is_enough_cache_available(
+ &mut self,
+ app: &App,
+ max_cache_size: u64,
+ next_video: &Video,
+ ) -> Result<CacheSizeCheck> {
+ if let Some(cdownload) = &self.current_download {
+ if cdownload.extractor_hash == next_video.extractor_hash {
+ // If the video is already being downloaded it will always fit. Otherwise the
+ // download would not have been started.
+ return Ok(CacheSizeCheck::Fits);
+ }
+ }
+ let cache_allocation = Self::get_current_cache_allocation(&app).await?;
+ let video_size = self.get_approx_video_size(&app, &next_video).await?;
+
+ if video_size >= max_cache_size {
+ error!(
+ "The video '{}' ({}) exceeds the maximum cache size ({})! \
+ Please set a bigger maximum (`--max-cache-size`) or skip it.",
+ next_video.title,
+ Bytes::new(video_size),
+ Bytes::new(max_cache_size)
+ );
+
+ return Ok(CacheSizeCheck::ExceedsMaxCacheSize);
+ }
+
+ if cache_allocation + video_size >= max_cache_size {
+ if !self.printed_warning {
+ warn!(
+ "Can't download video: '{}' ({}) as it's too large for the cache ({} of {} allocated). \
+ Waiting for cache size reduction..",
+ next_video.title, Bytes::new(video_size), Bytes::new(cache_allocation), Bytes::new(max_cache_size)
+ );
+ self.printed_warning = true;
+ }
+ if let Some(cca) = self.cached_cache_allocation {
+ if cca != cache_allocation {
+ warn!(
+ "Current cache size has changed, it's now: '{}'",
+ Bytes::new(cache_allocation)
+ );
+ self.cached_cache_allocation = Some(cache_allocation);
+ }
+ } else {
+ info!(
+ "Current cache size allocation: '{}'",
+ Bytes::new(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;
+ Ok(CacheSizeCheck::TooLarge)
+ } else {
+ self.printed_warning = false;
+ Ok(CacheSizeCheck::Fits)
}
}
@@ -72,18 +150,14 @@ impl Downloader {
/// This will run, until the database doesn't contain any watchable videos
pub async fn consume(&mut self, app: Arc<App>, max_cache_size: u64) -> Result<()> {
while let Some(next_video) = get_next_uncached_video(&app).await? {
- let cache_allocation = Self::get_current_cache_allocation(&app).await?;
- let video_size = self.get_approx_video_size(&app, &next_video).await?;
- if cache_allocation + video_size >= max_cache_size {
- warn!(
- "Can't download video: '{}' ({}) as it's too large for the cache ({} of {} allocated).",
- next_video.title, Bytes::new(video_size), Bytes::new(cache_allocation), Bytes::new(max_cache_size)
- );
-
- // Wait and hope, that a large video is deleted from the cache.
- time::sleep(Duration::from_secs(10)).await;
- continue;
- }
+ match self
+ .is_enough_cache_available(&app, max_cache_size, &next_video)
+ .await?
+ {
+ CacheSizeCheck::Fits => (),
+ CacheSizeCheck::TooLarge => continue,
+ CacheSizeCheck::ExceedsMaxCacheSize => bail!("Giving up."),
+ };
if let Some(_) = &self.current_download {
let current_download = self.current_download.take().expect("Is Some");