e071841ec2
Rewrite documentation to match the new architecture where all file metadata lives in PostgreSQL and content is stored as content-addressed blobs via DedupService. Updated files: - internal-architecture.md: complete rewrite — new DB schema, blob repos (FolderDb, FileBlobRead/Write, TrashDb), updated DI container, service groups, architecture diagram, data flows - file-system-safety.md: repurposed as storage-safety.md — covers PostgreSQL ACID guarantees + DedupService atomic writes - caching-architecture.md: updated repo references to blob repos, removed write-behind cache section, updated upload/download flows - trash-feature-summary.md: rewritten for soft-delete model (is_trashed flag, trash_items VIEW, TrashDbRepository) - share-integration.md: clarified ShareFsRepository scope, updated DI snippet, added blob storage context note - deduplication.md: updated DI snippet (dedup injected into repos) - deployment.md: updated feature matrix (file storage requires DB) - important-delta-sync-implementation.md: updated DI references Removed legacy references: IdMappingPort, StorageMediator, WriteBehindCache, FsFileRepository, FsFolderRepository, TrashFsRepository, folder_ids.json, file_ids.json.
118 lines
5.1 KiB
Markdown
118 lines
5.1 KiB
Markdown
# 14 - Trash Feature
|
|
|
|
Soft-delete for files and folders. Items go to a per-user trash bin instead of being permanently removed. Configurable retention period with automatic cleanup.
|
|
|
|
## Architecture
|
|
|
|
Follows the hexagonal architecture:
|
|
|
|
1. **Domain Layer** (`/src/domain/`):
|
|
- Entities: **TrashedItem** representing files and folders in the trash
|
|
- Repository interfaces: **TrashRepository** defining trash management operations
|
|
|
|
2. **Application Layer** (`/src/application/`):
|
|
- DTOs: **TrashedItemDto** for data transfer between layers
|
|
- Ports: **TrashUseCase** defining available operations
|
|
- Services: **TrashService** implementing the trash use cases
|
|
|
|
3. **Infrastructure Layer** (`/src/infrastructure/`):
|
|
- Repositories: **TrashDbRepository** (PostgreSQL) — reads from `storage.trash_items` VIEW, manages soft-delete flags
|
|
- Trash-related methods in file/folder repositories: `FileBlobWriteRepository::move_to_trash()`, `FolderDbRepository::move_to_trash()`, etc.
|
|
- Services: **TrashCleanupService** for automatic cleanup of expired items
|
|
|
|
4. **Interface Layer** (`/src/interfaces/`):
|
|
- API handlers: `trash_handler.rs` with HTTP endpoints for trash operations
|
|
- Routes: updated `routes.rs` to include trash endpoints
|
|
|
|
## Storage Model
|
|
|
|
Trash uses a **soft-delete** model in PostgreSQL:
|
|
|
|
- Files and folders have `is_trashed` (BOOLEAN) and `trashed_at` (TIMESTAMPTZ) columns
|
|
- When an item is trashed, `is_trashed` is set to `TRUE` and `trashed_at` records the timestamp
|
|
- `original_parent_id` / `original_folder_id` stores the original location for restore
|
|
- The `storage.trash_items` VIEW provides a unified list of all trashed items (files + folders)
|
|
- No physical file movement occurs — blob content stays at `.blobs/{prefix}/{hash}.blob`
|
|
- Permanent deletion removes the DB row and decrements the blob reference counter
|
|
|
|
```sql
|
|
CREATE OR REPLACE VIEW storage.trash_items AS
|
|
SELECT id, name, 'file' AS item_type, folder_id AS parent_id,
|
|
user_id, size, mime_type, trashed_at, created_at
|
|
FROM storage.files WHERE is_trashed = TRUE
|
|
UNION ALL
|
|
SELECT id, name, 'folder' AS item_type, parent_id,
|
|
user_id, 0 AS size, NULL AS mime_type, trashed_at, created_at
|
|
FROM storage.folders WHERE is_trashed = TRUE;
|
|
```
|
|
|
|
## Key Features
|
|
|
|
1. **Soft Deletion** — files and folders are flagged as trashed, not immediately deleted
|
|
2. **Per-User Trash** — each user has an isolated trash bin (filtered by `user_id`)
|
|
3. **Retention Policy** — items auto-delete after a configurable period
|
|
4. **Restoration** — items can be restored to their original location via `original_parent_id`/`original_folder_id`
|
|
5. **Permanent Deletion** — items can be permanently deleted before retention expires (removes DB row + decrements blob ref)
|
|
6. **Empty Trash** — wipe everything in the trash at once
|
|
|
|
## API Endpoints
|
|
|
|
- `GET /api/trash` or `GET /api/trash/` — list all items in the user's trash
|
|
- `DELETE /api/trash/files/:id` — move a file to trash
|
|
- `DELETE /api/trash/folders/:id` — move a folder to trash
|
|
- `POST /api/trash/:id/restore` — restore an item to its original location
|
|
- `DELETE /api/trash/:id` — permanently delete an item from trash
|
|
- `DELETE /api/trash/empty` — empty the entire trash bin
|
|
|
|
## Implementation Details
|
|
|
|
### TrashDbRepository
|
|
|
|
**File:** `src/infrastructure/repositories/pg/trash_db_repository.rs`
|
|
|
|
```rust
|
|
pub struct TrashDbRepository {
|
|
pool: Arc<PgPool>,
|
|
retention_days: u32,
|
|
}
|
|
```
|
|
|
|
Key methods:
|
|
- `get_trash_items(user_id)` — SELECT from `storage.trash_items` WHERE `user_id = $1`
|
|
- `clear_trash(user_id)` — DELETE from `storage.files` and `storage.folders` WHERE `is_trashed = TRUE AND user_id = $1`
|
|
- `get_expired_items()` — finds items where `trashed_at + retention_days < NOW()`
|
|
|
|
### TrashService
|
|
|
|
**File:** `src/application/services/trash_service.rs`
|
|
|
|
Constructor: `TrashService::new(trash_repo, file_read, file_write, folder_repo, retention_days)`
|
|
|
|
Orchestrates trash operations by delegating to the appropriate repository:
|
|
- Moving a file to trash → `FileBlobWriteRepository::move_to_trash()`
|
|
- Moving a folder to trash → `FolderDbRepository::move_to_trash()`
|
|
- Permanent deletion → removes DB row + calls `DedupService::decrement_ref()` to clean blob if unreferenced
|
|
|
|
### TrashCleanupService
|
|
|
|
**File:** `src/infrastructure/services/trash_cleanup_service.rs`
|
|
|
|
Background job that runs every 24 hours to permanently delete items past the retention period.
|
|
|
|
## Testing
|
|
|
|
1. **Unit Tests** — testing **TrashService**:
|
|
- Move files and folders to trash
|
|
- Restore items from trash
|
|
- Permanent deletion
|
|
- Empty trash operation
|
|
|
|
2. **Integration Tests** — Python script hitting the API endpoints:
|
|
- End-to-end testing of all trash operations
|
|
- Verification of move, list, restore, and delete behavior
|
|
|
|
## Configuration
|
|
|
|
- **OXICLOUD_ENABLE_TRASH**: enable/disable the trash feature via **FeaturesConfig** (default: true)
|
|
- **OXICLOUD_TRASH_RETENTION_DAYS**: days to keep items before automatic deletion (default: 30, via **StorageConfig**)
|