aboutsummaryrefslogtreecommitdiff
path: root/base/src
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2024-01-05 02:38:34 +0100
committermetamuffin <metamuffin@disroot.org>2024-01-05 02:38:34 +0100
commita5ad49451e80cae7ec7f5d2a216084aa30e2e704 (patch)
tree9fafbfed0c539045dcabb2fcf56539e8c35535af /base/src
parent7608522c8fdf46b93877da3fee4f21df3496beec (diff)
downloadjellything-a5ad49451e80cae7ec7f5d2a216084aa30e2e704.tar
jellything-a5ad49451e80cae7ec7f5d2a216084aa30e2e704.tar.bz2
jellything-a5ad49451e80cae7ec7f5d2a216084aa30e2e704.tar.zst
atomic cache insertion
Diffstat (limited to 'base/src')
-rw-r--r--base/src/cache.rs22
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)