Skip to content

Commit b62b6a2

Browse files
committed
fix(cache): clean up stale output archives on cache update
Each cache update writes a fresh UUID-named archive into the cache directory; the previous archive for the same key was being abandoned on disk, causing the cache directory to grow unboundedly with each re-execution of a cached task. `ExecutionCache::update` now reads the prior entry and removes the old archive file (best-effort) before upserting the new value. Also: - restore alphabetical ordering for `zstd` in the workspace Cargo.toml and `uuid` in `vite_task/Cargo.toml` - add a CHANGELOG entry for the new `output` field
1 parent f9a4f39 commit b62b6a2

5 files changed

Lines changed: 21 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Changelog
22

3+
- **Added** `output` field for cached tasks: archives output files after a successful run and restores them on cache hit. Defaults to automatically tracking files the task writes; accepts globs (e.g. `"dist/**"`), `{ "auto": true }`, and negative patterns (`"!dist/cache/**"`) ([#321](https://github.com/voidzero-dev/vite-task/pull/321))
34
- **Fixed** `vp run --cache` now supports running without a task specifier and opens the interactive task selector, matching bare `vp run` behavior ([#312](https://github.com/voidzero-dev/vite-task/pull/313))
45
- **Fixed** Ctrl-C now prevents future tasks from being scheduled and prevents caching of in-flight task results ([#309](https://github.com/voidzero-dev/vite-task/pull/309))
56
- **Added** `--concurrency-limit` flag to limit the number of tasks running at the same time (defaults to 4) ([#288](https://github.com/voidzero-dev/vite-task/pull/288), [#309](https://github.com/voidzero-dev/vite-task/pull/309))

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,6 @@ tui-term = "0.3.1"
136136
twox-hash = "2.1.1"
137137
uuid = "1.18.1"
138138
vec1 = "1.12.1"
139-
zstd = "0.13"
140139
vite_glob = { path = "crates/vite_glob" }
141140
vite_graph_ser = { path = "crates/vite_graph_ser" }
142141
vite_path = { path = "crates/vite_path" }
@@ -155,6 +154,7 @@ widestring = "1.2.0"
155154
winapi = "0.3.9"
156155
winsafe = { version = "0.0.24", features = ["kernel"] }
157156
xxhash-rust = { version = "0.8.15", features = ["const_xxh3"] }
157+
zstd = "0.13"
158158

159159
[workspace.metadata.cargo-shear]
160160
ignored = [

crates/vite_task/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,13 @@ tokio = { workspace = true, features = ["rt-multi-thread", "io-std", "io-util",
3636
tokio-util = { workspace = true }
3737
tracing = { workspace = true }
3838
twox-hash = { workspace = true }
39+
uuid = { workspace = true, features = ["v4"] }
3940
vite_path = { workspace = true }
4041
vite_select = { workspace = true }
4142
vite_str = { workspace = true }
4243
vite_task_graph = { workspace = true }
4344
vite_task_plan = { workspace = true }
4445
vite_workspace = { workspace = true }
45-
uuid = { workspace = true, features = ["v4"] }
4646
wax = { workspace = true }
4747
zstd = { workspace = true }
4848

crates/vite_task/src/session/cache/mod.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,16 +274,33 @@ impl ExecutionCache {
274274
}
275275

276276
/// Update cache after successful execution.
277+
///
278+
/// If a previous entry exists for the same cache key with a different
279+
/// `output_archive`, the stale archive file in `cache_dir` is removed
280+
/// (best-effort) so it doesn't accumulate on disk.
277281
#[tracing::instrument(level = "debug", skip_all)]
278282
pub async fn update(
279283
&self,
280284
cache_metadata: &CacheMetadata,
281285
cache_value: CacheEntryValue,
286+
cache_dir: &AbsolutePath,
282287
) -> anyhow::Result<()> {
283288
let execution_cache_key = &cache_metadata.execution_cache_key;
284289

285290
let cache_key = CacheEntryKey::from_metadata(cache_metadata);
286291

292+
// If a previous entry exists with a stale output archive, delete the
293+
// old file so the cache directory doesn't accumulate orphaned archives.
294+
if let Some(old_value) = self.get_by_cache_key(&cache_key).await?
295+
&& let Some(old_archive) = old_value.output_archive
296+
&& cache_value.output_archive.as_ref() != Some(&old_archive)
297+
{
298+
let old_archive_path = cache_dir.join(old_archive.as_str());
299+
// Best-effort cleanup: a missing file (e.g. after a crash or manual
300+
// cache clear) is fine, so we ignore the error.
301+
let _ = std::fs::remove_file(old_archive_path.as_path());
302+
}
303+
287304
self.upsert_cache_entry(&cache_key, &cache_value).await?;
288305
self.upsert_task_fingerprint(execution_cache_key, &cache_key).await?;
289306
Ok(())

crates/vite_task/src/session/execute/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ pub async fn execute_spawn(
532532
globbed_inputs,
533533
output_archive,
534534
};
535-
match cache.update(cache_metadata, new_cache_value).await {
535+
match cache.update(cache_metadata, new_cache_value, cache_dir).await {
536536
Ok(()) => (CacheUpdateStatus::Updated, None),
537537
Err(err) => (
538538
CacheUpdateStatus::NotUpdated(

0 commit comments

Comments
 (0)