feat: improve batch task controls and release 1.2.0
This commit is contained in:
1 parent
0e13bb5c29
commit
84e183d28d
38 files changed
+632
-147
No files matched your search
@@ -1158,11 +1158,21 @@ class StorageManager:
|
||||
"""Delete all data associated with a session, including files on disk."""
|
||||
session_id_str = str(session_id)
|
||||
|
||||
# 1. Get video paths before deleting from DB
|
||||
# 1. Get files referenced by this session before deleting from DB.
|
||||
video_paths = []
|
||||
video_ids: list[str] = []
|
||||
image_names: set[str] = set()
|
||||
try:
|
||||
with self._get_connection() as conn:
|
||||
image_names = {
|
||||
str(name)
|
||||
for row in conn.execute(
|
||||
"SELECT pre_image_name, post_image_name FROM steps WHERE session_id = ?",
|
||||
(session_id_str,),
|
||||
)
|
||||
for name in row
|
||||
if name
|
||||
}
|
||||
cursor = conn.execute(
|
||||
"SELECT video_id, local_video_path FROM video_recordings WHERE session_id = ?",
|
||||
(session_id_str,),
|
||||
@@ -1173,9 +1183,11 @@ class StorageManager:
|
||||
if row["local_video_path"]:
|
||||
video_paths.append(Path(row["local_video_path"]))
|
||||
except sqlite3.OperationalError as e:
|
||||
logger.warning(f"Could not query video_recordings: {e}")
|
||||
logger.warning(f"Could not query session media: {e}")
|
||||
raise
|
||||
|
||||
# 2. Delete from DB tables
|
||||
orphaned_images: list[str] = []
|
||||
with self._get_connection() as conn:
|
||||
conn.execute("PRAGMA foreign_keys = OFF")
|
||||
board_keys = [f"session:{session_id_str}"] + [
|
||||
@@ -1207,13 +1219,26 @@ class StorageManager:
|
||||
(session_id_str,),
|
||||
)
|
||||
except sqlite3.OperationalError as e:
|
||||
logger.warning(f"Failed to delete from table {table}: {e}")
|
||||
conn.commit()
|
||||
conn.execute("VACUUM")
|
||||
logger.error(f"Failed to delete from table {table}: {e}")
|
||||
raise
|
||||
for name in image_names:
|
||||
if not conn.execute(
|
||||
"SELECT 1 FROM steps WHERE pre_image_name=? OR post_image_name=? LIMIT 1",
|
||||
(name, name),
|
||||
).fetchone():
|
||||
conn.execute("DELETE FROM images WHERE image_name=?", (name,))
|
||||
orphaned_images.append(name)
|
||||
conn.commit()
|
||||
|
||||
logger.info(f"Database records for session {session_id} cleared.")
|
||||
|
||||
images_root = (self.base_trace_dir / "images").resolve()
|
||||
for name in orphaned_images:
|
||||
if len(name) == 64 and all(c in "0123456789abcdef" for c in name):
|
||||
image_path = (images_root / f"{name}.jpg").resolve()
|
||||
if image_path.is_relative_to(images_root):
|
||||
image_path.unlink(missing_ok=True)
|
||||
|
||||
# 3. Delete session directory (notes, etc.)
|
||||
session_dir = self.base_trace_dir / session_id_str
|
||||
if session_dir.exists() and session_dir.is_dir():
|
||||
@@ -1222,38 +1247,15 @@ class StorageManager:
|
||||
logger.info(f"Deleted session directory: {session_dir}")
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to delete session directory {session_dir}: {e}")
|
||||
raise
|
||||
|
||||
# 4. Delete video files and their containing folders (which might have been renamed)
|
||||
# 4. Never let a persisted recording path remove a sibling session.
|
||||
trace_root = self.base_trace_dir.resolve()
|
||||
for video_path in video_paths:
|
||||
# video_path is likely: /path/to/traces/task_name/recording.mp4
|
||||
# If it was renamed, it might be: /path/to/traces/task_name_PASS_timestamp/recording.mp4
|
||||
|
||||
task_name = video_path.parent.name
|
||||
|
||||
if task_name and task_name != "traces" and task_name != "..":
|
||||
# Search for directories starting with task_name in base_trace_dir
|
||||
try:
|
||||
for path in self.base_trace_dir.iterdir():
|
||||
if path.is_dir() and path.name.startswith(task_name):
|
||||
try:
|
||||
shutil.rmtree(path)
|
||||
logger.info(f"Deleted trace/video directory: {path}")
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to delete directory {path}: {e}")
|
||||
elif path.is_file() and path.name.startswith(task_name):
|
||||
try:
|
||||
path.unlink()
|
||||
logger.info(f"Deleted trace/video file: {path}")
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to delete file {path}: {e}")
|
||||
except Exception as e:
|
||||
logger.error(f"Error iterating base_trace_dir for cleanup: {e}")
|
||||
|
||||
if video_path.exists():
|
||||
try:
|
||||
video_path.unlink()
|
||||
logger.info(f"Deleted video file directly: {video_path}")
|
||||
if video_path.parent.exists() and not any(video_path.parent.iterdir()):
|
||||
video_path.parent.rmdir()
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to delete video file directly {video_path}: {e}")
|
||||
resolved = video_path.resolve()
|
||||
if not resolved.is_relative_to(trace_root):
|
||||
continue
|
||||
relative = resolved.relative_to(trace_root)
|
||||
if not relative.parts or relative.parts[0] != session_id_str:
|
||||
continue
|
||||
resolved.unlink(missing_ok=True)
|
||||
Reference in new issue
Block a user