mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-30 04:57:54 -06:00
Disk cache: evict before writing, reset the disk reading when the folder changes (#2551)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
8af5f54c92
commit
52dda004a5
@@ -119,6 +119,7 @@ impl Session {
|
||||
// (no file system in the browser: the disk cache stays off there)
|
||||
let Some(folder) = folder.filter(|_| d.disk_cache_enabled && !cfg!(target_arch = "wasm32")) else {
|
||||
self.disk_cache = None;
|
||||
self.disk_watch = Default::default();
|
||||
self.layer_cache.set_disk(None);
|
||||
return;
|
||||
};
|
||||
@@ -132,11 +133,17 @@ impl Session {
|
||||
c.set_max_bytes(max);
|
||||
c.clone()
|
||||
}
|
||||
// A new folder: the free-space reading was for the old one (a reader still running
|
||||
// holds the old watcher's state, so it can't write into the new one).
|
||||
_ => match DiskCache::open(&folder, max) {
|
||||
Ok(c) => c,
|
||||
Ok(c) => {
|
||||
self.disk_watch = Default::default();
|
||||
c
|
||||
}
|
||||
Err(e) => {
|
||||
log::warn!("disk cache at {}: {e}", folder.display());
|
||||
self.disk_cache = None;
|
||||
self.disk_watch = Default::default();
|
||||
self.layer_cache.set_disk(None);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -547,6 +547,8 @@ impl DiskCache {
|
||||
if data.len() as u64 > self.limit_bytes() {
|
||||
return;
|
||||
}
|
||||
// Make room first, so the cache never exceeds its limit (or the free-space reserve).
|
||||
self.evict_to(self.limit_bytes().saturating_sub(data.len() as u64));
|
||||
let n = self.tmp_counter.fetch_add(1, Ordering::Relaxed);
|
||||
let tmp = parent.join(format!("{key:032x}.tmp.{}.{n}", std::process::id()));
|
||||
if let Err(e) = std::fs::write(&tmp, &data).and_then(|()| std::fs::rename(&tmp, &path)) {
|
||||
@@ -558,7 +560,6 @@ impl DiskCache {
|
||||
if let Ok(mut g) = self.index.lock() {
|
||||
g.insert(kind, key, data.len() as u64);
|
||||
}
|
||||
self.evict();
|
||||
}
|
||||
|
||||
/// Count a failed write; the first one is logged (a full disk shouldn't go unnoticed).
|
||||
@@ -570,7 +571,11 @@ impl DiskCache {
|
||||
|
||||
/// Remove least recently used entries until the cache fits its limit.
|
||||
fn evict(&self) {
|
||||
let max = self.limit_bytes();
|
||||
self.evict_to(self.limit_bytes());
|
||||
}
|
||||
|
||||
/// Remove least recently used entries until the cache fits `max` bytes.
|
||||
fn evict_to(&self, max: u64) {
|
||||
let victims = match self.index.lock() {
|
||||
Ok(mut g) => g.evict(max),
|
||||
Err(_) => return,
|
||||
@@ -1134,7 +1139,7 @@ mod tests {
|
||||
assert_eq!((st.max_bytes, st.limit_bytes), (1 << 30, used));
|
||||
dc.put_layer_now(9, &buf(9, 64, 64));
|
||||
let st = dc.stats();
|
||||
assert!(st.bytes <= used - used / 10 && st.evictions > 0, "{st:?}");
|
||||
assert!(st.bytes <= st.limit_bytes && st.bytes <= used - used / 10 && st.evictions > 0, "{st:?}");
|
||||
assert!(dc.contains(Kind::Layer, 9), "the new entry is the most recently used");
|
||||
// Below the reserve the cache gives its space back, and skips writes that can't fit.
|
||||
dc.set_disk_space(Some((100 << 30, 4 << 30)));
|
||||
|
||||
Reference in New Issue
Block a user