2.7 KiB
2.7 KiB
Lifecycle & Removal Specification
This document defines the "Dislike \rightarrow Delayed Deletion" lifecycle. This state machine ensures user intent is respected while preventing accidental permanent loss of music.
1. The Dislike State Machine
A track follows this state transition to ensure a "Grace Period" before physical deletion.
| Current State | Action | Next State | Side Effects |
|---|---|---|---|
| LIBRARY | User Dislikes | PENDING_REMOVAL | dislikes row created; Track becomes HIDDEN. |
| PENDING_REMOVAL | User Restores | LIBRARY | dislikes row deleted; Track becomes VISIBLE. |
| PENDING_REMOVAL | Grace Period Ends | WARNING_SENT | ntfy notification sent; warned_at timestamp set. |
| WARNING_SENT | 24h Passes | DELETED | File deleted from FS; Track record removed from DB. |
2. Detailed Transitions
Phase 1: The Dislike (Immediate)
When a user triggers a dislike:
- DB Transaction:
- Update
tracks.state = 'HIDDEN'. - Insert into
dislikestable{track_id, disliked_at: now}. - Log
feedback(action='disliked').
- Update
- UI Update: The track immediately disappears from all "active" views (Library, Playlists, Vibe Queue, Search).
Phase 2: The Grace Period (The "Safety Net")
- Duration (
X): Configurable (default: 48 hours). - Behavior: The track remains on disk and in the database, but is filtered out of all user-facing discovery and playback.
Phase 3: The Warning (The "Nudge")
When now > disliked_at + X:
- Worker Action: The
Cleanup/Sweep Workeridentifies the track. - Notification: Sends a message via
ntfy(e.g., "Are you sure? '' is scheduled for deletion in 24h"). - DB Update: Set
dislikes.warned_at = now.
Phase 4: The Finality (The "Cleanup")
When now > warned_at + 24h:
- FS Action: Delete the physical file at
tracks.path. - DB Action:
- Cascade delete all related records (history, play_counts, etc.).
- Remove the
tracksrecord.
- Logging: Log
feedback(action='deleted_permanent').
2. Safety Invariants
- No Immediate Deletion: No user action (other than a "Hard Delete" admin command) can trigger immediate file deletion.
- State Consistency: A track cannot be in
PENDING_REMOVALandLIBRARYsimultaneously. - Atomic Deletion: The file deletion and the database removal must be treated as a single logical unit of work to prevent "Orphaned Files" (files on disk with no DB record) or "Ghost Records" (DB records with no file).
3. User Recovery
The "Restore" action is a simple reversal:
DELETE FROM dislikes WHERE track_id = X;UPDATE tracks SET state = 'LIBRARY' WHERE id = X;