Add delete marker support to paths
Introduce DeleteMarker struct and associated functions for managing soft-delete markers within case directories. This enables tracking deleted cases and supports undo functionality. feat: Add delete marker support to paths Introduces a `.deleted` file to mark cases as soft-deleted. The marker contains a `batch` UUID for grouping deletions and a `deleted_at` timestamp for ordering. New functions `is_deleted`, `read_delete_marker`, and `write_delete_marker` are added to manage this marker. The `locate_case` function is updated to also consider soft-deleted cases as not found.
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
/// Absolute on-disk location of a case directory.
|
||||
///
|
||||
/// Single source of truth for the layout `<data_path>/<slug>/<case_id>/`.
|
||||
@@ -8,3 +11,41 @@ use std::path::{Path, PathBuf};
|
||||
pub fn case_dir(data_path: &Path, slug: &str, case_id: &str) -> PathBuf {
|
||||
data_path.join(slug).join(case_id)
|
||||
}
|
||||
|
||||
/// Filename of the soft-delete marker inside a case directory.
|
||||
pub const DELETE_MARKER: &str = ".deleted";
|
||||
|
||||
/// Soft-delete marker payload. One file per deleted case; all cases removed
|
||||
/// in the same user click share the same `batch` UUID. `deleted_at` is an
|
||||
/// RFC3339 timestamp — used to find the most recent batch for "Undo last
|
||||
/// delete".
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct DeleteMarker {
|
||||
pub batch: Uuid,
|
||||
pub deleted_at: String,
|
||||
}
|
||||
|
||||
/// True iff the case directory contains a `.deleted` marker file.
|
||||
pub async fn is_deleted(case_dir: &Path) -> bool {
|
||||
tokio::fs::try_exists(case_dir.join(DELETE_MARKER))
|
||||
.await
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Read and parse the `.deleted` marker. Returns `None` if absent or malformed
|
||||
/// (treated identically — a malformed marker still means "deleted" via
|
||||
/// `is_deleted`, but cannot participate in batch-undo).
|
||||
pub async fn read_delete_marker(case_dir: &Path) -> Option<DeleteMarker> {
|
||||
let bytes = tokio::fs::read(case_dir.join(DELETE_MARKER)).await.ok()?;
|
||||
serde_json::from_slice(&bytes).ok()
|
||||
}
|
||||
|
||||
/// Write the `.deleted` marker as JSON. Overwrites any existing marker.
|
||||
pub async fn write_delete_marker(
|
||||
case_dir: &Path,
|
||||
marker: &DeleteMarker,
|
||||
) -> std::io::Result<()> {
|
||||
let bytes = serde_json::to_vec(marker)
|
||||
.map_err(|e| std::io::Error::other(format!("serialize delete marker: {e}")))?;
|
||||
tokio::fs::write(case_dir.join(DELETE_MARKER), bytes).await
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user