turbo_tasks_backend/database/
db_versioning.rs1use std::{
2 env,
3 fs::{metadata, read_dir, remove_dir_all},
4 path::{Path, PathBuf},
5 time::Duration,
6};
7
8use anyhow::Result;
9
10pub struct GitVersionInfo<'a> {
16 pub describe: &'a str,
18 pub dirty: bool,
21}
22
23const MAX_OTHER_DB_VERSIONS: usize = 2;
27
28pub fn handle_db_versioning(base_path: &Path, version_info: &GitVersionInfo) -> Result<PathBuf> {
29 if let Ok(version) = env::var("TURBO_ENGINE_VERSION") {
30 return Ok(base_path.join(version));
31 }
32 let ignore_dirty = env::var("TURBO_ENGINE_IGNORE_DIRTY").ok().is_some();
36 let disabled_versioning = env::var("TURBO_ENGINE_DISABLE_VERSIONING").ok().is_some();
37 let version = if disabled_versioning {
38 println!(
39 "WARNING: Persistent Caching versioning is disabled. Manual removal of the persistent \
40 caching database might be required."
41 );
42 Some("unversioned")
43 } else if !version_info.dirty {
44 Some(version_info.describe)
45 } else if ignore_dirty {
46 println!(
47 "WARNING: The git repository is dirty, but Persistent Caching is still enabled. \
48 Manual removal of the persistent caching database might be required."
49 );
50 Some(version_info.describe)
51 } else {
52 println!(
53 "WARNING: The git repository is dirty: Persistent Caching is disabled. Use \
54 TURBO_ENGINE_IGNORE_DIRTY=1 to ignore dirtyness of the repository."
55 );
56 None
57 };
58 let path;
59 if let Some(version) = version {
60 path = base_path.join(version);
61
62 if let Ok(read_dir) = read_dir(base_path) {
64 let old_dbs = read_dir
65 .filter_map(|entry| {
66 let entry = entry.ok()?;
67 if !entry.file_type().ok()?.is_dir() {
68 return None;
69 }
70 let name = entry.file_name();
71 let name = name.to_string_lossy();
72 if name == version {
73 return None;
74 }
75 Some(entry.path())
76 })
77 .collect::<Vec<_>>();
78 if old_dbs.len() > MAX_OTHER_DB_VERSIONS {
79 let mut old_dbs = old_dbs
80 .iter()
81 .map(|p| {
82 fn get_age(p: &Path) -> Result<Duration> {
83 let m = metadata(p)?;
84 Ok(m.accessed().or_else(|_| m.modified())?.elapsed()?)
85 }
86 (
87 p,
88 get_age(p).unwrap_or(Duration::from_secs(10 * 356 * 24 * 60 * 60)),
89 )
90 })
91 .collect::<Vec<_>>();
92 old_dbs.sort_by_key(|(_, age)| *age);
93 for (p, _) in old_dbs.into_iter().skip(MAX_OTHER_DB_VERSIONS) {
94 let _ = remove_dir_all(p);
95 }
96 }
97 }
98 } else {
99 path = base_path.join("temp");
100 let _ = remove_dir_all(&path);
101 }
102
103 Ok(path)
104}