From a5ad49451e80cae7ec7f5d2a216084aa30e2e704 Mon Sep 17 00:00:00 2001 From: metamuffin Date: Fri, 5 Jan 2024 02:38:34 +0100 Subject: atomic cache insertion --- base/src/cache.rs | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'base/src') 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::()))?) + .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::()))?) + .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) -- cgit v1.2.3-70-g09d2