Files
muzick/docs/architecture/06-lifecycle-spec.md
T

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:

  1. DB Transaction:
    • Update tracks.state = 'HIDDEN'.
    • Insert into dislikes table {track_id, disliked_at: now}.
    • Log feedback(action='disliked').
  2. 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:

  1. Worker Action: The Cleanup/Sweep Worker identifies the track.
  2. Notification: Sends a message via ntfy (e.g., "Are you sure? '' is scheduled for deletion in 24h").
  3. DB Update: Set dislikes.warned_at = now.

Phase 4: The Finality (The "Cleanup")

When now > warned_at + 24h:

  1. FS Action: Delete the physical file at tracks.path.
  2. DB Action:
    • Cascade delete all related records (history, play_counts, etc.).
    • Remove the tracks record.
  3. 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_REMOVAL and LIBRARY simultaneously.
  • 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;