Grace period for inaccessible workspaces (#50829)

Oussama ELJabbari created

Closes #49603

Release Notes:
- Added a 7-day grace period to prevent recently used local workspaces
from being deleted when their paths are temporarily unavailable. Session
workspaces are always preserved on restart.

Change summary

crates/workspace/src/persistence.rs | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)

Detailed changes

crates/workspace/src/persistence.rs 🔗

@@ -1784,11 +1784,17 @@ impl WorkspaceDb {
         }
     }
 
-    async fn all_paths_exist_with_a_directory(paths: &[PathBuf], fs: &dyn Fs) -> bool {
+    async fn all_paths_exist_with_a_directory(
+        paths: &[PathBuf],
+        fs: &dyn Fs,
+        timestamp: Option<DateTime<Utc>>,
+    ) -> bool {
         let mut any_dir = false;
         for path in paths {
             match fs.metadata(path).await.ok().flatten() {
-                None => return false,
+                None => {
+                    return timestamp.is_some_and(|t| Utc::now() - t < chrono::Duration::days(7));
+                }
                 Some(meta) => {
                     if meta.is_dir {
                         any_dir = true;
@@ -1844,7 +1850,9 @@ impl WorkspaceDb {
             // If a local workspace points to WSL, this check will cause us to wait for the
             // WSL VM and file server to boot up. This can block for many seconds.
             // Supported scenarios use remote workspaces.
-            if !has_wsl_path && Self::all_paths_exist_with_a_directory(paths.paths(), fs).await {
+            if !has_wsl_path
+                && Self::all_paths_exist_with_a_directory(paths.paths(), fs, Some(timestamp)).await
+            {
                 result.push((id, SerializedWorkspaceLocation::Local, paths, timestamp));
             } else {
                 delete_tasks.push(self.delete_workspace_by_id(id));
@@ -1904,7 +1912,7 @@ impl WorkspaceDb {
                     window_id,
                 });
             } else {
-                if Self::all_paths_exist_with_a_directory(paths.paths(), fs).await {
+                if Self::all_paths_exist_with_a_directory(paths.paths(), fs, None).await {
                     workspaces.push(SessionWorkspace {
                         workspace_id,
                         location: SerializedWorkspaceLocation::Local,