diff options
author | metamuffin <metamuffin@disroot.org> | 2024-01-05 02:38:34 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2024-01-05 02:38:34 +0100 |
commit | a5ad49451e80cae7ec7f5d2a216084aa30e2e704 (patch) | |
tree | 9fafbfed0c539045dcabb2fcf56539e8c35535af /base/src | |
parent | 7608522c8fdf46b93877da3fee4f21df3496beec (diff) | |
download | jellything-a5ad49451e80cae7ec7f5d2a216084aa30e2e704.tar jellything-a5ad49451e80cae7ec7f5d2a216084aa30e2e704.tar.bz2 jellything-a5ad49451e80cae7ec7f5d2a216084aa30e2e704.tar.zst |
atomic cache insertion
Diffstat (limited to 'base/src')
-rw-r--r-- | base/src/cache.rs | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/base/src/cache.rs b/base/src/cache.rs index d2d7990..e580130 100644 --- a/base/src/cache.rs +++ b/base/src/cache.rs @@ -9,11 +9,15 @@ use base64::Engine; use bincode::{Decode, Encode}; use jellycommon::AssetLocation; use log::{info, warn}; +use rand::random; use std::{ any::Any, collections::{BTreeMap, HashMap}, + fs::rename, future::Future, io::Seek, + path::PathBuf, + str::FromStr, sync::{ atomic::{AtomicUsize, Ordering}, Arc, LazyLock, RwLock, @@ -58,17 +62,23 @@ where .await .context("unable to test for cache file existance")?; if !exists { - let f = tokio::fs::File::create(location.path()) + let temp_path = + AssetLocation::Cache(PathBuf::from_str(&format!("temp-{:x}", random::<u128>()))?) + .path(); + let f = tokio::fs::File::create(&temp_path) .await .context("creating new cache file")?; match generate(f).await { Ok(()) => (), Err(e) => { warn!("cache generation failed, unlinking entry"); - tokio::fs::remove_file(location.path()).await?; + tokio::fs::remove_file(temp_path).await?; return Err(e); } } + tokio::fs::rename(temp_path, location.path()) + .await + .context("rename cache")?; } drop(_guard); Ok(location) @@ -83,15 +93,19 @@ where let _guard = CACHE_GENERATION_LOCKS[bucket % CACHE_GENERATION_BUCKET_COUNT].blocking_lock(); let exists = location.path().exists(); if !exists { - let f = std::fs::File::create(location.path()).context("creating new cache file")?; + let temp_path = + AssetLocation::Cache(PathBuf::from_str(&format!("temp-{:x}", random::<u128>()))?) + .path(); + let f = std::fs::File::create(&temp_path).context("creating new cache file")?; match generate(f) { Ok(()) => (), Err(e) => { warn!("cache generation failed, unlinking entry"); - std::fs::remove_file(location.path())?; + std::fs::remove_file(temp_path)?; return Err(e); } } + rename(temp_path, location.path()).context("rename cache")?; } drop(_guard); Ok(location) |