Skip to main content

LineageStore

Struct LineageStore 

Source
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

The whole lineage graph, kept relational for a clean SQLite migration.

nodes and resolution_cache are BTreeMaps and edges is sorted after every update, so serialisation is deterministic.

Fields§

§schema_version: u32

On-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

Source

pub fn new() -> Self

Create an empty store at the current schema version.

Source

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.

Source

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.

Source

pub fn node(&self, id: &str) -> Option<&Node>

The node for id, if present.

Source

pub fn owner(&self) -> Option<&Owner>

The account this library is pinned to, if any.

Source

pub fn owner_check(&self, user_id: &str) -> OwnerCheck

Compare an authenticated user_id against the pinned owner.

Source

pub fn pin_owner(&mut self, owner: Owner)

Pin this library to owner, replacing any prior pin.

Source

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.

Source

pub fn get_root(&self, id: &str) -> Option<&CacheEntry>

The cached root resolution for id, if present.

Source

pub fn album_art(&self, root_id: &str) -> Option<&AlbumArt>

The reconciled folder-art state for the album rooted at root_id.

Source

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.

Source

pub fn playlist(&self, id: &str) -> Option<&PlaylistState>

The reconciled .m3u8 state for the playlist with id, if present.

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub fn len(&self) -> usize

Number of nodes in the graph.

Source

pub fn is_empty(&self) -> bool

True when the graph holds no nodes.

Source

pub fn iter(&self) -> Iter<'_, String, Node>

Iterate nodes in clip-id order.

Source

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

Source§

fn clone(&self) -> LineageStore

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for LineageStore

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for LineageStore

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for LineageStore

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

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.

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Serialize for LineageStore

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.