11//! Execution cache for storing and retrieving cached command results.
22
3+ pub mod archive;
34pub mod display;
45
56use std:: { collections:: BTreeMap , fmt:: Display , fs:: File , io:: Write , sync:: Arc , time:: Duration } ;
@@ -15,7 +16,8 @@ use rusqlite::{Connection, OptionalExtension as _, config::DbConfig};
1516use serde:: { Deserialize , Serialize } ;
1617use tokio:: sync:: Mutex ;
1718use vite_path:: { AbsolutePath , RelativePathBuf } ;
18- use vite_task_graph:: config:: ResolvedInputConfig ;
19+ use vite_str:: Str ;
20+ use vite_task_graph:: config:: ResolvedGlobConfig ;
1921use vite_task_plan:: cache_metadata:: { CacheMetadata , ExecutionCacheKey , SpawnFingerprint } ;
2022
2123use super :: execute:: { fingerprint:: PostRunFingerprint , spawn:: StdOutput } ;
@@ -38,14 +40,18 @@ pub struct CacheEntryKey {
3840 pub spawn_fingerprint : SpawnFingerprint ,
3941 /// Resolved input configuration that affects cache behavior.
4042 /// Glob patterns are workspace-root-relative.
41- pub input_config : ResolvedInputConfig ,
43+ pub input_config : ResolvedGlobConfig ,
44+ /// Resolved output configuration that affects cache restoration.
45+ /// Glob patterns are workspace-root-relative.
46+ pub output_config : ResolvedGlobConfig ,
4247}
4348
4449impl CacheEntryKey {
4550 fn from_metadata ( cache_metadata : & CacheMetadata ) -> Self {
4651 Self {
4752 spawn_fingerprint : cache_metadata. spawn_fingerprint . clone ( ) ,
4853 input_config : cache_metadata. input_config . clone ( ) ,
54+ output_config : cache_metadata. output_config . clone ( ) ,
4955 }
5056 }
5157}
@@ -64,6 +70,9 @@ pub struct CacheEntryValue {
6470 /// Path is relative to workspace root, value is `xxHash3_64` of file content.
6571 /// Stored in the value (not the key) so changes can be detected and reported.
6672 pub globbed_inputs : BTreeMap < RelativePathBuf , u64 > ,
73+ /// Filename of the output archive (e.g. `{uuid}.tar.zst`) stored alongside
74+ /// `cache.db` in the cache directory. `None` if no output files were produced.
75+ pub output_archive : Option < Str > ,
6776}
6877
6978#[ derive( Debug ) ]
@@ -105,6 +114,8 @@ pub enum FingerprintMismatch {
105114 } ,
106115 /// Found a previous cache entry key for the same task, but `input_config` differs.
107116 InputConfig ,
117+ /// Found a previous cache entry key for the same task, but `output_config` differs.
118+ OutputConfig ,
108119
109120 InputChanged {
110121 kind : InputChangeKind ,
@@ -121,6 +132,9 @@ impl Display for FingerprintMismatch {
121132 Self :: InputConfig => {
122133 write ! ( f, "input configuration changed" )
123134 }
135+ Self :: OutputConfig => {
136+ write ! ( f, "output configuration changed" )
137+ }
124138 Self :: InputChanged { kind, path } => {
125139 write ! ( f, "{}" , display:: format_input_change_str( * kind, path. as_str( ) ) )
126140 }
@@ -168,16 +182,16 @@ impl ExecutionCache {
168182 "CREATE TABLE task_fingerprints (key BLOB PRIMARY KEY, value BLOB);" ,
169183 ( ) ,
170184 ) ?;
171- conn. execute ( "PRAGMA user_version = 10 " , ( ) ) ?;
185+ conn. execute ( "PRAGMA user_version = 11 " , ( ) ) ?;
172186 }
173- 1 ..=9 => {
187+ 1 ..=10 => {
174188 // old internal db version. reset
175189 conn. set_db_config ( DbConfig :: SQLITE_DBCONFIG_RESET_DATABASE , true ) ?;
176190 conn. execute ( "VACUUM" , ( ) ) ?;
177191 conn. set_db_config ( DbConfig :: SQLITE_DBCONFIG_RESET_DATABASE , false ) ?;
178192 }
179- 10 => break , // current version
180- 11 .. => {
193+ 11 => break , // current version
194+ 12 .. => {
181195 return Err ( anyhow:: anyhow!( "Unrecognized database version: {user_version}" ) ) ;
182196 }
183197 }
@@ -233,11 +247,20 @@ impl ExecutionCache {
233247 self . get_cache_key_by_execution_key ( execution_cache_key) . await ?
234248 {
235249 // Destructure to ensure we handle all fields when new ones are added
236- let CacheEntryKey { spawn_fingerprint : old_spawn_fingerprint, input_config : _ } =
237- old_cache_key;
250+ let CacheEntryKey {
251+ spawn_fingerprint : old_spawn_fingerprint,
252+ input_config : old_input_config,
253+ output_config : old_output_config,
254+ } = old_cache_key;
238255 let mismatch = if old_spawn_fingerprint == * spawn_fingerprint {
239- // spawn fingerprint is the same but input_config or glob_base changed
240- FingerprintMismatch :: InputConfig
256+ // spawn fingerprint is the same but input_config or output_config changed
257+ if old_input_config != cache_metadata. input_config {
258+ FingerprintMismatch :: InputConfig
259+ } else if old_output_config != cache_metadata. output_config {
260+ FingerprintMismatch :: OutputConfig
261+ } else {
262+ FingerprintMismatch :: InputConfig
263+ }
241264 } else {
242265 FingerprintMismatch :: SpawnFingerprint {
243266 old : old_spawn_fingerprint,
0 commit comments