pub struct LineageStore {
pub schema_version: u32,
pub nodes: BTreeMap<String, Node>,
pub edges: Vec<StoredEdge>,
pub resolution_cache: BTreeMap<String, CacheEntry>,
pub albums: BTreeMap<String, AlbumArt>,
pub playlists: BTreeMap<String, PlaylistState>,
pub owner: Option<Owner>,
pub album_overrides: BTreeMap<String, String>,
/* private fields */
}Expand description
Fields§
§schema_version: u32On-disk schema version, so a future migration can branch on it.
nodes: BTreeMap<String, Node>Every clip ever seen (including trashed ancestors), keyed by clip id.
edges: Vec<StoredEdge>Every observed parent link, as a flat relational list.
resolution_cache: BTreeMap<String, CacheEntry>The last resolved (or last-known) root per clip, keyed by clip id.
albums: BTreeMap<String, AlbumArt>The reconciled folder-art state per album, keyed by the album’s stable root id (HARDENING H2). Additive: absent in older stores, defaults empty.
playlists: BTreeMap<String, PlaylistState>The reconciled .m3u8 state per playlist, keyed by the playlist’s Suno
id (the synthetic "liked" id for the liked feed). Additive: absent in
older stores, defaults empty.
owner: Option<Owner>The Suno account this library is pinned to (trust-on-first-use). Absent in older stores and in a fresh library until the first run adopts it.
album_overrides: BTreeMap<String, String>Manual album-name overrides, keyed by lineage root id, layered over the
store each run from config (see set_album_overrides). Runtime-only:
it is never serialised, so it can never persist into the durable graph or
silently outlive its config entry.
Implementations§
Source§impl LineageStore
impl LineageStore
Sourcepub fn set_album_overrides(&mut self, overrides: BTreeMap<String, String>)
pub fn set_album_overrides(&mut self, overrides: BTreeMap<String, String>)
Layer this run’s manual album-name overrides onto the store.
Keyed by lineage root id, sourced from the account’s config each run and
never persisted (the field is #[serde(skip)]). Applied wherever the
album title is resolved (context_for, album_for_id,
colliding_root_titles), so a single call makes the folder path, the
ALBUM tag, the change hash, the on-disk index, and disambiguation all
reflect the preferred name from one source of truth.
Sourcepub fn refresh_eligible_roots(&mut self)
pub fn refresh_eligible_roots(&mut self)
Recompute the eligible-root set from the resolution cache.
The set is the non-empty root_ids across the cache’s values (the roots
every clip resolves to), which is exactly what colliding_root_titles
groups over. Called at the end of update and after a load (the field
is not serialised), so the set always reflects the populated cache.
Sourcepub fn owner_check(&self, user_id: &str) -> OwnerCheck
pub fn owner_check(&self, user_id: &str) -> OwnerCheck
Compare an authenticated user_id against the pinned owner.
Sourcepub fn refresh_display_name(&mut self, display_name: &str) -> bool
pub fn refresh_display_name(&mut self, display_name: &str) -> bool
Refresh the pinned owner’s display name when it has changed, returning whether it changed. A no-op when the library is not pinned.
Sourcepub fn get_root(&self, id: &str) -> Option<&CacheEntry>
pub fn get_root(&self, id: &str) -> Option<&CacheEntry>
The cached root resolution for id, if present.
Sourcepub fn album_art(&self, root_id: &str) -> Option<&AlbumArt>
pub fn album_art(&self, root_id: &str) -> Option<&AlbumArt>
The reconciled folder-art state for the album rooted at root_id.
Sourcepub fn set_album_artifact(
&mut self,
root_id: &str,
kind: ArtifactKind,
state: Option<ArtifactState>,
)
pub fn set_album_artifact( &mut self, root_id: &str, kind: ArtifactKind, state: Option<ArtifactState>, )
Set (or clear, with None) one folder-art kind for the album rooted at
root_id.
A set upserts the album row; a clear that empties the row removes it, so
the store never accumulates dead all-None album entries. This is the
store-level counterpart the CLI persists after the executor mutates the
albums map in place.
Sourcepub fn playlist(&self, id: &str) -> Option<&PlaylistState>
pub fn playlist(&self, id: &str) -> Option<&PlaylistState>
The reconciled .m3u8 state for the playlist with id, if present.
Sourcepub fn set_playlist(&mut self, id: &str, state: Option<PlaylistState>)
pub fn set_playlist(&mut self, id: &str, state: Option<PlaylistState>)
Upsert (with Some) or remove (with None) the .m3u8 state for the
playlist id.
This is the store-level counterpart the CLI persists after the executor
mutates the playlists map in place: a write records
the new state; a delete clears the row so the store never keeps a
dangling entry for a playlist whose file was removed.
Sourcepub fn context_for(&self, clip: &Clip) -> LineageContext
pub fn context_for(&self, clip: &Clip) -> LineageContext
Build a LineageContext for clip from the durable store.
This is the source of truth for every file-affecting lineage decision (album folder, embedded tags, the change hash), so a dropped resolution call never rewrites the library (HARDENING H3). The root comes from the monotonic resolution cache (the clip’s own id when the store has no better answer) and the root title from that root’s archived node, so a transient miss keeps the last-known-good album even for a since-purged ancestor. The parent edge is read structurally from the clip itself.
Sourcepub fn album_for_id(&self, id: &str) -> String
pub fn album_for_id(&self, id: &str) -> String
The canonical logical album title for a clip identified only by id.
The store-side counterpart of context_for(clip).album(clip.title) for a
clip that is not part of the current run (so no live Clip is on hand).
The clip’s own title and its root come from the archived nodes and the
monotonic resolution cache, then the same LineageContext::album rule
decides whether the clip folders under its root’s album or its own title.
A clip absent from the store folds to a self-root with an empty title.
Sourcepub fn colliding_root_titles(&self) -> BTreeSet<String>
pub fn colliding_root_titles(&self) -> BTreeSet<String>
The set of effective album titles shared by more than one distinct root.
Two distinct roots must never share an album folder (two different
uploads titled “Break Through” exist), so naming appends the short root
id to the album of any clip whose album is in this set. It is computed
from the whole archive — every eligible root (see
eligible_root_ids) paired with its effective
title (a manual override when configured, else the node title) — so the
decision is stable across runs and independent of the current batch: a
--since/--limit slice that shows only one of two same-titled roots
still disambiguates, instead of oscillating between a bare and a suffixed
folder. Because it folds overrides in first, a rename that collides two
albums (or one that resolves a collision) is honoured consistently with
the path, tag, and hash.
This iterates the exact same eligible-root set that
effective_root_title gates overrides on,
so an override affects a root’s album name if and only if that root is
grouped here — the two can never disagree. The set is the non-empty
root_ids appearing as cache values, so it includes gap-filled/archived
ancestor roots (a value for their children, never a key) and node-less
cached roots. A root with no node and no override has an empty effective
title and is skipped. An uncached fallback self-root on a
resolution-failed run is in neither set.
Sourcepub fn update(&mut self, clips: &[Clip], resolution: &Resolution, now: &str)
pub fn update(&mut self, clips: &[Clip], resolution: &Resolution, now: &str)
Fold this run’s clips and their Resolution into the store.
Pure: it takes now (an ISO timestamp) from the caller rather than
reading a clock. Upserts a node for every clip and every gap-filled
ancestor (so trashed ancestors are archived), upserts an edge for every
lineage_edges link, and refreshes the monotonic resolution cache.
edges is left sorted so the serialised form is deterministic.
Trait Implementations§
Source§impl Clone for LineageStore
impl Clone for LineageStore
Source§fn clone(&self) -> LineageStore
fn clone(&self) -> LineageStore
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for LineageStore
impl Debug for LineageStore
Source§impl Default for LineageStore
impl Default for LineageStore
Source§impl<'de> Deserialize<'de> for LineageStorewhere
LineageStore: Default,
impl<'de> Deserialize<'de> for LineageStorewhere
LineageStore: Default,
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl PartialEq for LineageStore
Equality over the durable graph only.
impl PartialEq for LineageStore
Equality over the durable graph only.
album_overrides and eligible_root_ids are runtime-only overlays
(#[serde(skip)]): the first is layered from config each run, the second is
a cache derived from resolution_cache. Neither is part of the persisted
relational shape, so two stores are equal when their durable content is,
regardless of the overrides in force or whether the derived set has been
refreshed after a load.