Documentation
¶
Index ¶
- Constants
- Variables
- func BackupsDir(dataDir string) string
- func IsUpdateSnapshotName(name string) bool
- func MappingsFromConfig(cfg *config.Instance) []database.Mapping
- func NormalizeID(uid string) string
- func RestoreFileTo(ctx context.Context, fs afero.Fs, backupPath, dbPath string) error
- func SchemaProvenance(dbPath string) (version string, ok bool)
- type UserDB
- func (db *UserDB) APIDiagnostics() apidiag.DatabaseSnapshot
- func (db *UserDB) ActivateProfile(profileID string, lastUsedAt int64) error
- func (db *UserDB) AddHistory(entry *database.HistoryEntry) error
- func (db *UserDB) AddInboxMessage(msg *database.InboxMessage) (*database.InboxMessage, error)
- func (db *UserDB) AddMapping(m *database.Mapping) error
- func (db *UserDB) AddMediaHistory(entry *database.MediaHistoryEntry) (int64, error)
- func (db *UserDB) Allocate() error
- func (db *UserDB) BackfillMediaHistoryUUIDs() (int64, error)
- func (db *UserDB) Backup(reason string, manual bool) (database.BackupInfo, error)
- func (db *UserDB) BackupForTransfer(ctx context.Context, reason string) (database.BackupInfo, func() error, error)
- func (db *UserDB) BackupForUpdate(targetVersion string) (database.BackupInfo, func() error, error)
- func (db *UserDB) ClaimRemoteCommand(command *database.RemoteCommand) (*database.RemoteCommand, bool, error)
- func (db *UserDB) CleanupHistory(retentionDays int) (int64, error)
- func (db *UserDB) CleanupMediaHistory(retentionDays int, requireSynced bool) (int64, error)
- func (db *UserDB) ClearCorruptMarker() error
- func (db *UserDB) ClearDeckSync() error
- func (db *UserDB) ClearLibraryStateSync() error
- func (db *UserDB) Close() error
- func (db *UserDB) CloseHangingMediaHistory() error
- func (db *UserDB) CloseMediaHistory(dbid int64, endTime time.Time, playTime int) error
- func (db *UserDB) CountClients() (int, error)
- func (db *UserDB) CountOwnedDecks() (int, error)
- func (db *UserDB) CreateClient(c *database.Client) error
- func (db *UserDB) CreateDeck(deck *database.Deck) error
- func (db *UserDB) CreateProfile(p *database.Profile) error
- func (db *UserDB) DeleteAllInboxMessages() (int64, error)
- func (db *UserDB) DeleteClient(clientID string) error
- func (db *UserDB) DeleteDeck(deckID string) (bool, error)
- func (db *UserDB) DeleteDeckSync(deckIDs []string) error
- func (db *UserDB) DeleteDeviceState(key string) error
- func (db *UserDB) DeleteInboxMessage(id int64) error
- func (db *UserDB) DeleteLibraryStateSync(identityKeys []string) error
- func (db *UserDB) DeleteMapping(id int64) error
- func (db *UserDB) DeleteMediaUserData(systemID, path string) error
- func (db *UserDB) DeleteProfile(profileID string) error
- func (db *UserDB) EnsureRecentBackup(maxAge time.Duration) (database.BackupInfo, bool, error)
- func (db *UserDB) GetAllMappings() ([]database.Mapping, error)
- func (db *UserDB) GetClientByToken(authToken string) (*database.Client, error)
- func (db *UserDB) GetDBPath() string
- func (db *UserDB) GetDeck(deckID string) (*database.Deck, error)
- func (db *UserDB) GetDeckSync(deckID string) (database.DeckSyncRow, bool, error)
- func (db *UserDB) GetDeviceState(key string) (value string, found bool, err error)
- func (db *UserDB) GetDistinctMediaHistory(ctx context.Context, systemIDs []string, lastID int64, limit int) ([]database.MediaHistoryEntry, error)
- func (db *UserDB) GetEnabledMappings() ([]database.Mapping, error)
- func (db *UserDB) GetHistory(lastID int64) ([]database.HistoryEntry, error)
- func (db *UserDB) GetInboxMessages() ([]database.InboxMessage, error)
- func (db *UserDB) GetLatestMediaHistory() (database.MediaHistoryEntry, bool, error)
- func (db *UserDB) GetMapping(id int64) (database.Mapping, error)
- func (db *UserDB) GetMediaHistory(systemIDs []string, lastID int64, limit int) ([]database.MediaHistoryEntry, error)
- func (db *UserDB) GetMediaHistoryIdentityBackfillBatch(afterDBID int64, policyVersion int, limit int) ([]database.MediaHistoryEntry, error)
- func (db *UserDB) GetMediaHistorySyncBatch(after time.Time, afterDBID int64, limit int) ([]database.MediaHistoryEntry, error)
- func (db *UserDB) GetMediaHistoryTop(systemIDs []string, since *time.Time, limit int) ([]database.MediaHistoryTopEntry, error)
- func (db *UserDB) GetMediaUserData(systemID, path string) (database.MediaUserData, bool, error)
- func (db *UserDB) GetProfile(profileID string) (*database.Profile, error)
- func (db *UserDB) GetProfileBySwitchID(switchID string) (*database.Profile, error)
- func (db *UserDB) GetSupportedZapLinkHosts() ([]string, error)
- func (db *UserDB) GetZapLinkCache(url string) (string, error)
- func (db *UserDB) GetZapLinkHost(host string) (supported, found bool, err error)
- func (db *UserDB) HealTimestamps(bootUUID string, trueBootTime time.Time) (int64, error)
- func (db *UserDB) IntegrityReport() []string
- func (db *UserDB) IsMarkedCorrupt() bool
- func (db *UserDB) ListBackups() ([]database.BackupInfo, error)
- func (db *UserDB) ListClients() ([]database.Client, error)
- func (db *UserDB) ListDeckSync() ([]database.DeckSyncRow, error)
- func (db *UserDB) ListDecks() ([]database.Deck, error)
- func (db *UserDB) ListLibraryStateSync() ([]database.LibraryStateSyncRow, error)
- func (db *UserDB) ListMediaUserData() ([]database.MediaUserData, error)
- func (db *UserDB) ListProfiles() ([]database.Profile, error)
- func (db *UserDB) ListRecentRemoteCommands(limit int) ([]database.RemoteCommand, error)
- func (db *UserDB) ListUnreportedRemoteCommands(limit int) ([]database.RemoteCommand, error)
- func (db *UserDB) MarkCorrupt(reason string)
- func (db *UserDB) MarkMediaHistorySynced(refs []database.MediaHistorySyncRef, syncedAt time.Time) error
- func (db *UserDB) MarkRemoteCommandResultReported(commandID string) error
- func (db *UserDB) MigrateUp() error
- func (db *UserDB) NoteCorruption(err error) bool
- func (db *UserDB) Open() error
- func (db *UserDB) PruneExpiredZapLinkHosts(olderThan time.Duration) (int64, error)
- func (db *UserDB) PruneRemoteCommands(before time.Time) (int64, error)
- func (db *UserDB) RecoverFromCorruption() (database.RestoreInfo, error)
- func (db *UserDB) RenameDeck(oldID, newID string) error
- func (db *UserDB) ReplaceAllClients(clients []database.Client) error
- func (db *UserDB) ResetMediaHistorySyncAfter(watermark *time.Time) error
- func (db *UserDB) RestoreBackup(name string) (database.RestoreInfo, error)
- func (db *UserDB) SetDeckItemAnchor(itemDBID int64, anchor *database.DeckItemAnchor) error
- func (db *UserDB) SetDeviceState(key, value string) error
- func (db *UserDB) SetMediaUserFavorite(systemID, path string, favorite bool) error
- func (db *UserDB) SetMediaUserFlag(systemID, path string, flag database.MediaUserFlag, value bool) error
- func (db *UserDB) SetMediaUserHidden(systemID, path string, hidden bool) error
- func (db *UserDB) SetMediaUserLauncherOverride(systemID, path, launcherID string) error
- func (db *UserDB) SetMediaUserSnapshot(systemID, path, mediaName, slug string, tags []string) error
- func (db *UserDB) SetSQLForTesting(ctx context.Context, sqlDB *sql.DB, platform platforms.Platform) error
- func (db *UserDB) StoreRemoteCommandResult(commandID, fromState, status string, result json.RawMessage, errorCode string) (bool, error)
- func (db *UserDB) SumMediaPlayTimeForDay(dayStart time.Time) (int64, error)
- func (db *UserDB) SumMediaPlayTimeForDayByProfile(dayStart time.Time, profileID string) (int64, error)
- func (db *UserDB) TransitionRemoteCommand(commandID, fromState, toState string, executionExpiresAt *time.Time) (bool, error)
- func (db *UserDB) Truncate() error
- func (db *UserDB) UnsafeGetSQLDb() *sql.DB
- func (db *UserDB) UpdateClientLastSeen(authToken string, lastSeenAt int64) error
- func (db *UserDB) UpdateDeck(deckID string, edit func(deck *database.Deck) error) (*database.Deck, error)
- func (db *UserDB) UpdateMapping(id int64, m *database.Mapping) error
- func (db *UserDB) UpdateMediaHistoryIdentity(dbid int64, identity *database.MediaIdentity) (bool, error)
- func (db *UserDB) UpdateMediaHistoryIdentityAndPath(dbid int64, path string, identity *database.MediaIdentity) (bool, error)
- func (db *UserDB) UpdateMediaHistoryTime(dbid int64, playTime int) error
- func (db *UserDB) UpdateProfile(p *database.Profile) error
- func (db *UserDB) UpdateZapLinkCache(url, zapscript string) error
- func (db *UserDB) UpdateZapLinkHost(host string, zapscript int) error
- func (db *UserDB) UpsertDeckSync(rows []database.DeckSyncRow) error
- func (db *UserDB) UpsertFetchedDeck(deck *database.Deck, maxCopies int) (database.FetchedDeckResult, error)
- func (db *UserDB) UpsertLibraryStateSync(rows []database.LibraryStateSyncRow) error
- func (db *UserDB) UpsertMediaUserData(data *database.MediaUserData) error
- func (db *UserDB) UpsertRemoteDeck(deck *database.Deck) (bool, error)
- func (db *UserDB) Vacuum() error
Constants ¶
const ( MappingTypeID = "id" MappingTypeValue = "value" MappingTypeData = "data" MatchTypeExact = "exact" MatchTypePartial = "partial" MatchTypeRegex = "regex" LegacyMappingTypeUID = "uid" LegacyMappingTypeText = "text" )
Variables ¶
var ( // ErrProfileNotFound is returned when a profile lookup matches no row. ErrProfileNotFound = errors.New("profile not found") // ErrLastProfileAdmin is returned when an operation would remove the // final administrator profile. ErrLastProfileAdmin = errors.New("cannot remove the last admin profile") )
var AllowedMappingTypes = []string{ MappingTypeID, MappingTypeValue, MappingTypeData, }
var AllowedMatchTypes = []string{ MatchTypeExact, MatchTypePartial, MatchTypeRegex, }
var ErrConnDrainTimeout = errors.New("timed out waiting for user database queries to finish")
ErrConnDrainTimeout is returned when queries are still running after the connection pool has been closed and the drain deadline has passed.
var ErrInvalidAuthToken = errors.New("auth token must not contain ':'")
ErrInvalidAuthToken rejects ':' in auth tokens (AAD uses `<token>:ws`; also enforced by SQL CHECK).
var ErrInvalidBackup = errors.New("user database backup is invalid")
var ErrLastClientAdmin = errors.New("cannot delete the last admin client")
ErrLastClientAdmin is returned when deleting the final admin client.
var ErrNullSQL = errors.New("UserDB is not connected")
Functions ¶
func BackupsDir ¶ added in v2.17.0
BackupsDir returns the directory backups live in for a data directory, so a caller with no open database can still find them.
func IsUpdateSnapshotName ¶ added in v2.17.0
IsUpdateSnapshotName reports whether name is an update snapshot. The updater needs this to reclaim snapshots whose update is long resolved, and it holds no database handle when it runs.
func MappingsFromConfig ¶ added in v2.15.0
MappingsFromConfig converts the file-based mappings loaded into config into the database.Mapping shape used for matching and API responses. The returned mappings are always enabled and carry no database ID, since they originate from the mappings folder rather than UserDB.
func NormalizeID ¶
func RestoreFileTo ¶ added in v2.17.0
RestoreFileTo installs a backup over a user database that nothing has open.
RestoreBackup is the normal path and cannot be used here: it needs a live *UserDB, and the only way to get one is OpenUserDB, which creates a fresh empty schema when the file is missing. The update watchdog runs before any database is opened — that is what lets it decide without consulting a schema version — so it needs the swap on its own.
The backup is quick_checked first, because installing a corrupt file over a working database turns a recoverable situation into an unrecoverable one. A crash partway through is repaired by recoverInterruptedRestore, which Open already runs before anything else touches the file.
func SchemaProvenance ¶ added in v2.18.0
SchemaProvenance reports the version of Zaparoo that last migrated the user database at dbPath, without going through the normal open path.
It is meant for the case where the normal open path has already refused: the schema is newer than this build understands, so nothing here may migrate, write or otherwise touch the file. The connection is read-only for that reason.
ok is false when the file, the table or the row is absent, which is the normal answer for a database last written by a build from before this was recorded. Callers have to read well without it.
Types ¶
type UserDB ¶
type UserDB struct {
// contains filtered or unexported fields
}
func (*UserDB) APIDiagnostics ¶ added in v2.18.0
func (db *UserDB) APIDiagnostics() apidiag.DatabaseSnapshot
func (*UserDB) ActivateProfile ¶ added in v2.16.0
ActivateProfile atomically records profile use and persists it as active.
func (*UserDB) AddHistory ¶
func (db *UserDB) AddHistory(entry *database.HistoryEntry) error
func (*UserDB) AddInboxMessage ¶ added in v2.8.0
func (db *UserDB) AddInboxMessage(msg *database.InboxMessage) (*database.InboxMessage, error)
func (*UserDB) AddMediaHistory ¶ added in v2.7.0
func (db *UserDB) AddMediaHistory(entry *database.MediaHistoryEntry) (int64, error)
AddMediaHistory adds a new media history entry and returns the DBID.
func (*UserDB) BackfillMediaHistoryUUIDs ¶ added in v2.16.0
BackfillMediaHistoryUUIDs assigns stable session UUIDs to legacy MediaHistory rows written before UUIDs existed. Existing timestamps remain unchanged.
func (*UserDB) BackupForTransfer ¶ added in v2.16.0
func (db *UserDB) BackupForTransfer( ctx context.Context, reason string, ) (database.BackupInfo, func() error, error)
BackupForTransfer creates a validated portable snapshot without paired-client credentials. Cleanup owns the private temporary directory and is safe to call more than once.
func (*UserDB) BackupForUpdate ¶ added in v2.17.0
func (db *UserDB) BackupForUpdate( targetVersion string, ) (database.BackupInfo, func() error, error)
BackupForUpdate drains and closes the live connection pool before taking the snapshot. The pool remains closed until the caller invokes resume after an aborted install; a successful install restarts the process instead. This closes the window where acknowledged outgoing-version writes could land after the rollback snapshot.
func (*UserDB) ClaimRemoteCommand ¶ added in v2.17.0
func (db *UserDB) ClaimRemoteCommand(command *database.RemoteCommand) (*database.RemoteCommand, bool, error)
func (*UserDB) CleanupHistory ¶ added in v2.7.0
func (*UserDB) CleanupMediaHistory ¶ added in v2.7.0
CleanupMediaHistory removes media history older than the retention period. When requireSynced is true, only server-acknowledged versions are removed.
func (*UserDB) ClearCorruptMarker ¶ added in v2.15.0
func (*UserDB) ClearDeckSync ¶ added in v2.18.0
ClearDeckSync removes every deck sync row.
func (*UserDB) ClearLibraryStateSync ¶ added in v2.18.0
ClearLibraryStateSync removes every personal state base row.
func (*UserDB) CloseHangingMediaHistory ¶ added in v2.7.0
CloseHangingMediaHistory closes any media history entries left open from unclean shutdowns. It sets EndTime = StartTime + PlayTime for entries where EndTime is NULL.
func (*UserDB) CloseMediaHistory ¶ added in v2.7.0
CloseMediaHistory finalizes a media history entry with end time and final play time.
func (*UserDB) CountClients ¶ added in v2.11.0
func (*UserDB) CountOwnedDecks ¶ added in v2.18.0
CountOwnedDecks returns how many decks this device owns.
func (*UserDB) CreateClient ¶ added in v2.11.0
func (*UserDB) CreateDeck ¶ added in v2.18.0
CreateDeck inserts a deck with its items. The deck's DeckID must already be minted and normalized. A deck fails with ErrDeckItemLimit past DeckMaxItems. How many decks a device holds is not capped: a deck costs well under ten kilobytes, and the work a deck creates is bounded per deck by DeckMaxItems rather than by their number.
func (*UserDB) CreateProfile ¶ added in v2.16.0
func (*UserDB) DeleteAllInboxMessages ¶ added in v2.8.0
func (*UserDB) DeleteClient ¶ added in v2.11.0
func (*UserDB) DeleteDeck ¶ added in v2.18.0
DeleteDeck removes a deck and its items. The bool reports whether a deck existed.
func (*UserDB) DeleteDeckSync ¶ added in v2.18.0
DeleteDeckSync removes the sync rows for the given decks.
func (*UserDB) DeleteDeviceState ¶ added in v2.16.0
func (*UserDB) DeleteInboxMessage ¶ added in v2.8.0
func (*UserDB) DeleteLibraryStateSync ¶ added in v2.18.0
DeleteLibraryStateSync removes the base rows for the given identities.
func (*UserDB) DeleteMapping ¶
func (*UserDB) DeleteMediaUserData ¶ added in v2.15.0
DeleteMediaUserData removes the user-data row for (SystemID, Path). Deleting a row that does not exist is not an error.
func (*UserDB) DeleteProfile ¶ added in v2.16.0
DeleteProfile removes a profile. If the profile is the device's active profile, the active-profile device state is cleared in the same transaction.
func (*UserDB) EnsureRecentBackup ¶ added in v2.15.0
func (*UserDB) GetClientByToken ¶ added in v2.11.0
func (*UserDB) GetDeck ¶ added in v2.18.0
GetDeck returns a deck with its items in position order, both read from the same snapshot.
func (*UserDB) GetDeckSync ¶ added in v2.18.0
GetDeckSync returns the sync row for one deck, if any.
func (*UserDB) GetDeviceState ¶ added in v2.16.0
GetDeviceState returns the value for key and whether it exists.
func (*UserDB) GetDistinctMediaHistory ¶ added in v2.17.0
func (db *UserDB) GetDistinctMediaHistory( ctx context.Context, systemIDs []string, lastID int64, limit int, ) ([]database.MediaHistoryEntry, error)
GetDistinctMediaHistory returns the newest lean history row for each (system, media path) identity, ordered for stable cursor pagination.
func (*UserDB) GetEnabledMappings ¶
func (*UserDB) GetHistory ¶
func (db *UserDB) GetHistory(lastID int64) ([]database.HistoryEntry, error)
func (*UserDB) GetInboxMessages ¶ added in v2.8.0
func (db *UserDB) GetInboxMessages() ([]database.InboxMessage, error)
func (*UserDB) GetLatestMediaHistory ¶ added in v2.14.0
func (db *UserDB) GetLatestMediaHistory() (database.MediaHistoryEntry, bool, error)
GetLatestMediaHistory retrieves the most recent media history entry with no enrichment.
func (*UserDB) GetMediaHistory ¶ added in v2.7.0
func (db *UserDB) GetMediaHistory(systemIDs []string, lastID int64, limit int) ([]database.MediaHistoryEntry, error)
GetMediaHistory retrieves media history entries with pagination and optional system filtering.
func (*UserDB) GetMediaHistoryIdentityBackfillBatch ¶ added in v2.16.1
func (db *UserDB) GetMediaHistoryIdentityBackfillBatch( afterDBID int64, policyVersion int, limit int, ) ([]database.MediaHistoryEntry, error)
GetMediaHistoryIdentityBackfillBatch returns legacy history rows whose scanner identity is absent or older than policyVersion. Future-policy rows are never selected for downgrade.
func (*UserDB) GetMediaHistorySyncBatch ¶ added in v2.16.0
func (db *UserDB) GetMediaHistorySyncBatch( after time.Time, afterDBID int64, limit int, ) ([]database.MediaHistoryEntry, error)
GetMediaHistorySyncBatch returns unsynced rows after the local (after, afterDBID) cursor in (UpdatedAt, DBID) order. Mutations clear SyncedAt, so acknowledged rows do not repeat and unreliable-clock rows remain eligible regardless of the server's timestamp watermark. Rows without a session UUID are excluded; startup backfills legacy rows first.
func (*UserDB) GetMediaHistoryTop ¶ added in v2.10.0
func (db *UserDB) GetMediaHistoryTop( systemIDs []string, since *time.Time, limit int, ) ([]database.MediaHistoryTopEntry, error)
GetMediaHistoryTop returns aggregated media history grouped by SystemID+MediaName, sorted by total play time descending.
func (*UserDB) GetMediaUserData ¶ added in v2.15.0
GetMediaUserData returns the user-data row for a media path. The bool is false when no row exists for the (systemID, path) key, in which case the media has no user preferences recorded.
func (*UserDB) GetProfile ¶ added in v2.16.0
func (*UserDB) GetProfileBySwitchID ¶ added in v2.16.0
func (*UserDB) GetSupportedZapLinkHosts ¶ added in v2.8.0
func (*UserDB) GetZapLinkHost ¶
func (*UserDB) HealTimestamps ¶ added in v2.7.0
HealTimestamps corrects timestamps for records created with unreliable clocks (MiSTer boot without NTP). When NTP syncs, this reconstructs correct timestamps using: TrueStartTime = TrueBootTime + MonotonicStart
func (*UserDB) IntegrityReport ¶ added in v2.15.0
func (*UserDB) IsMarkedCorrupt ¶ added in v2.15.0
func (*UserDB) ListBackups ¶ added in v2.15.0
func (db *UserDB) ListBackups() ([]database.BackupInfo, error)
func (*UserDB) ListClients ¶ added in v2.11.0
func (*UserDB) ListDeckSync ¶ added in v2.18.0
func (db *UserDB) ListDeckSync() ([]database.DeckSyncRow, error)
ListDeckSync returns every deck sync row.
func (*UserDB) ListDecks ¶ added in v2.18.0
ListDecks returns every deck without items, most recently updated first, with ItemCount filled in.
func (*UserDB) ListLibraryStateSync ¶ added in v2.18.0
func (db *UserDB) ListLibraryStateSync() ([]database.LibraryStateSyncRow, error)
ListLibraryStateSync returns every personal state base row.
func (*UserDB) ListMediaUserData ¶ added in v2.15.0
func (db *UserDB) ListMediaUserData() ([]database.MediaUserData, error)
ListMediaUserData returns every user-data row, used by the reindex re-apply step to re-materialize the media.db projection.
func (*UserDB) ListProfiles ¶ added in v2.16.0
func (*UserDB) ListRecentRemoteCommands ¶ added in v2.17.0
func (db *UserDB) ListRecentRemoteCommands(limit int) ([]database.RemoteCommand, error)
ListRecentRemoteCommands returns the most recently created remote commands, newest first, for display as an owner-facing activity log. limit is clamped to at least 1 by the caller.
func (*UserDB) ListUnreportedRemoteCommands ¶ added in v2.17.0
func (db *UserDB) ListUnreportedRemoteCommands(limit int) ([]database.RemoteCommand, error)
ListUnreportedRemoteCommands returns terminal commands whose result has not yet been posted, oldest first. limit bounds a single call so the caller can post the batch a little at a time; see remote.replayStoredResults.
func (*UserDB) MarkCorrupt ¶ added in v2.15.0
func (*UserDB) MarkMediaHistorySynced ¶ added in v2.16.0
func (db *UserDB) MarkMediaHistorySynced(refs []database.MediaHistorySyncRef, syncedAt time.Time) error
MarkMediaHistorySynced stamps SyncedAt only when each row still matches the uploaded version. Concurrent mutations advance UpdatedAt and remain unsynced.
func (*UserDB) MarkRemoteCommandResultReported ¶ added in v2.17.0
func (*UserDB) NoteCorruption ¶ added in v2.15.0
func (*UserDB) PruneExpiredZapLinkHosts ¶ added in v2.8.0
func (*UserDB) PruneRemoteCommands ¶ added in v2.17.0
func (*UserDB) RecoverFromCorruption ¶ added in v2.15.0
func (db *UserDB) RecoverFromCorruption() (database.RestoreInfo, error)
func (*UserDB) RenameDeck ¶ added in v2.18.0
RenameDeck moves a deck and its sync row to a new ID. Fails with ErrDeckNotFound when no deck holds oldID.
func (*UserDB) ReplaceAllClients ¶ added in v2.16.0
ReplaceAllClients atomically replaces every paired client row. Device backup restore uses this to carry the destination's paired clients across a restored user database, since portable snapshots are created without client rows.
func (*UserDB) ResetMediaHistorySyncAfter ¶ added in v2.16.0
ResetMediaHistorySyncAfter clears local acknowledgements newer than the server watermark so restored or reset server state is uploaded again. A nil watermark means the server has no sessions and resets every local row.
func (*UserDB) RestoreBackup ¶ added in v2.15.0
func (db *UserDB) RestoreBackup(name string) (database.RestoreInfo, error)
func (*UserDB) SetDeckItemAnchor ¶ added in v2.18.0
func (db *UserDB) SetDeckItemAnchor(itemDBID int64, anchor *database.DeckItemAnchor) error
SetDeckItemAnchor records the local file a game item resolved to. It never inserts.
func (*UserDB) SetDeviceState ¶ added in v2.16.0
func (*UserDB) SetMediaUserFavorite ¶ added in v2.15.0
SetMediaUserFavorite records (or clears) the favourite flag for a media path.
func (*UserDB) SetMediaUserFlag ¶ added in v2.18.0
func (db *UserDB) SetMediaUserFlag(systemID, path string, flag database.MediaUserFlag, value bool) error
SetMediaUserFlag records (or clears) one preference flag for a media path without disturbing the other columns on the same row, except for the flags the model forbids beside it: liked clears disliked and the reverse, and disliked clears favorite. The write is a column-scoped upsert plus a conditional delete, run in one transaction so two concurrent edits to the same path cannot read-modify-write over each other.
func (*UserDB) SetMediaUserHidden ¶ added in v2.18.0
SetMediaUserHidden changes visibility without disturbing other preferences.
func (*UserDB) SetMediaUserLauncherOverride ¶ added in v2.15.0
SetMediaUserLauncherOverride records (or clears, when launcherID is empty) the launcher-override intent for a media path without disturbing the flags on the same row. See SetMediaUserFlag for the concurrency guarantee.
func (*UserDB) SetMediaUserSnapshot ¶ added in v2.16.0
SetMediaUserSnapshot records a successfully resolved scanner identity snapshot on an existing user-data row. It never inserts: a snapshot without user intent is meaningless. Empty tags are significant and replace stale tags; callers must skip this method when lookup fails.
func (*UserDB) SetSQLForTesting ¶
func (db *UserDB) SetSQLForTesting(ctx context.Context, sqlDB *sql.DB, platform platforms.Platform) error
SetSQLForTesting allows injection of a sql.DB instance for testing purposes. This method should only be used in tests to set up in-memory databases.
func (*UserDB) StoreRemoteCommandResult ¶ added in v2.17.0
func (*UserDB) SumMediaPlayTimeForDay ¶ added in v2.15.0
SumMediaPlayTimeForDay returns the total seconds of completed play-time that overlaps with the day starting at dayStart. Sessions that span midnight are pro-rated: only the portion after dayStart is counted. The currently-active session (EndTime IS NULL) is excluded; callers add it separately.
func (*UserDB) SumMediaPlayTimeForDayByProfile ¶ added in v2.16.0
func (db *UserDB) SumMediaPlayTimeForDayByProfile(dayStart time.Time, profileID string) (int64, error)
SumMediaPlayTimeForDayByProfile is SumMediaPlayTimeForDay scoped to history attributed to a single profile. History with no profile (the shared profile) is counted by SumMediaPlayTimeForDay, which sums all rows: shared limits are device-level, so deactivating a profile must not grant a fresh daily allowance.
func (*UserDB) TransitionRemoteCommand ¶ added in v2.17.0
func (*UserDB) UnsafeGetSQLDb ¶
func (*UserDB) UpdateClientLastSeen ¶ added in v2.11.0
func (*UserDB) UpdateDeck ¶ added in v2.18.0
func (db *UserDB) UpdateDeck(deckID string, edit func(deck *database.Deck) error) (*database.Deck, error)
UpdateDeck edits a deck in one transaction. It loads the deck with its items, lets edit change the deck's Name, Description, Metadata and Items, and stores those fields; edit's other changes are ignored. An item that still carries the DBID of one of the deck's items keeps that row, so its ID and creation time survive the edit. Any other item is inserted, and rows no item kept are deleted. Positions follow list order from one. When edit fails, or leaves more than DeckMaxItems items, nothing is written. Returns the deck as stored.
func (*UserDB) UpdateMediaHistoryIdentity ¶ added in v2.16.0
func (db *UserDB) UpdateMediaHistoryIdentity(dbid int64, identity *database.MediaIdentity) (bool, error)
UpdateMediaHistoryIdentity stores a complete scanner identity snapshot and reports whether this policy version changed the history row.
func (*UserDB) UpdateMediaHistoryIdentityAndPath ¶ added in v2.17.0
func (db *UserDB) UpdateMediaHistoryIdentityAndPath( dbid int64, path string, identity *database.MediaIdentity, ) (bool, error)
UpdateMediaHistoryIdentityAndPath is UpdateMediaHistoryIdentity plus a MediaPath correction, for backfilling legacy rows recorded under a non-path external identifier (e.g. a MiSTer arcade set name).
func (*UserDB) UpdateMediaHistoryTime ¶ added in v2.7.0
UpdateMediaHistoryTime updates only the PlayTime for currently playing media.
func (*UserDB) UpdateProfile ¶ added in v2.16.0
func (*UserDB) UpdateZapLinkCache ¶
func (*UserDB) UpdateZapLinkHost ¶
func (*UserDB) UpsertDeckSync ¶ added in v2.18.0
func (db *UserDB) UpsertDeckSync(rows []database.DeckSyncRow) error
UpsertDeckSync stores deck sync rows, replacing rows for the same deck.
func (*UserDB) UpsertFetchedDeck ¶ added in v2.18.0
func (db *UserDB) UpsertFetchedDeck(deck *database.Deck, maxCopies int) (database.FetchedDeckResult, error)
UpsertFetchedDeck stores a deck fetched from a link as a read-only copy. The copy is known by deck.SourceURL alone: a link fetched before updates its stored copy, and any other link gets a deck ID minted on this device, so nothing the source serves can name, replace or hide another deck. At most maxCopies fetched decks are kept; past that the ones fetched longest ago are removed and reported, so their tags can be cleared.
func (*UserDB) UpsertLibraryStateSync ¶ added in v2.18.0
func (db *UserDB) UpsertLibraryStateSync(rows []database.LibraryStateSyncRow) error
UpsertLibraryStateSync stores personal state base rows, replacing rows with the same identity.
func (*UserDB) UpsertMediaUserData ¶ added in v2.15.0
func (db *UserDB) UpsertMediaUserData(data *database.MediaUserData) error
UpsertMediaUserData inserts or updates the user-data row for (SystemID, Path). CreatedAt is set on insert only; UpdatedAt is set on every write. A row with no flag set and no launcher override carries no user intent, so it is deleted rather than persisted. A row holding a forbidden flag pair is refused.
func (*UserDB) UpsertRemoteDeck ¶ added in v2.18.0
UpsertRemoteDeck inserts or fully replaces a deck that arrived from elsewhere (a ZapLink fetch or a sync pull), keeping the stored DBID and creation time. The deck's ID is normalized first. A cached copy of somebody else's deck never overwrites an owned deck of the same ID (ErrDeckOwned), so a tap on your own deck's ZapLink opens the editable local copy. A deck fails with ErrDeckItemLimit past DeckMaxItems.
An arriving item carries no row of its own, so one that matches a stored item exactly adopts that row and the local file it is linked to. Only what really changed is written, and a fetch that brings nothing new records that the deck was checked and nothing else. It reports whether the stored deck changed, so the caller can queue the deck's tags only when it did.