Documentation
¶
Index ¶
- Constants
- Variables
- func HeartbeatCapabilities(cfg *config.Instance) map[string]any
- func IsPlaySyncDisabledError(err error) bool
- func IsRateLimitedError(err error) bool
- func IsRemoteUnlinkedError(err error) bool
- func LibrarySyncCapability(cfg *config.Instance) map[string]any
- func RemoteAvailabilityNeedsRefresh(now time.Time, status *models.BackupStatusEntry) bool
- type APIError
- type BusyError
- type Coordinator
- type FileRef
- type Info
- type Lease
- type ListInfo
- type Manager
- func (m *Manager) Create(ctx context.Context) (Info, error)
- func (m *Manager) Delete(ctx context.Context, name string) error
- func (m *Manager) Inspect(ctx context.Context, name string) (Info, error)
- func (m *Manager) List() ([]ListInfo, error)
- func (m *Manager) ListRemote(ctx context.Context) (RemoteListInfo, error)
- func (m *Manager) MarkRemoteLinked()
- func (m *Manager) MarkRemoteUnlinked()
- func (m *Manager) NewOnlineClient(baseURL string) (*OnlineClient, error)
- func (m *Manager) NotifyScheduleStale()
- func (m *Manager) RecoverInterruptedRuns()
- func (m *Manager) RecoverRestore(ctx context.Context) error
- func (m *Manager) RefreshRemoteAvailability(ctx context.Context) (string, error)
- func (m *Manager) RefreshRemoteAvailabilityIfStale(ctx context.Context) (string, error)
- func (m *Manager) RefreshRemoteAvailabilityIfStaleAsync()
- func (m *Manager) Restore(ctx context.Context, name string) (RestoreInfo, error)
- func (m *Manager) RestoreRemote(ctx context.Context, id string) (RemoteRestoreInfo, error)
- func (m *Manager) RevokeRemoteLink(ctx context.Context) error
- func (m *Manager) RunRemote(ctx context.Context, backupType string) (RemoteRunInfo, error)
- func (m *Manager) SendCapabilityHeartbeat(ctx context.Context) error
- func (m *Manager) SendHeartbeat(ctx context.Context) error
- func (m *Manager) Status() models.BackupStatusResponse
- func (m *Manager) SyncPlayHistory(ctx context.Context) (PlaySyncInfo, error)
- func (m *Manager) TrackScheduleStale(now time.Time, active bool, staleAfter time.Duration) bool
- func (m *Manager) WithActiveMedia(activeMedia func() *models.ActiveMedia) *Manager
- func (m *Manager) WithCoordinator(coordinator *Coordinator) *Manager
- func (m *Manager) WithInbox(inbox *inboxservice.Service) *Manager
- func (m *Manager) WithPauser(pauser *syncutil.Pauser) *Manager
- func (m *Manager) WithRateLimitWaits(minWait, defaultWait, maxWait time.Duration) *Manager
- func (m *Manager) WithRefusedSessions(refused *RefusedSessions) *Manager
- func (m *Manager) WithRestoreGate(restoreGate func(context.Context) (func(bool), error)) *Manager
- type Manifest
- type OnlineClient
- func (o *OnlineClient) BaseURL() string
- func (o *OnlineClient) CredentialTag() string
- func (o *OnlineClient) DoBytes(ctx context.Context, method, path string, body []byte, headers http.Header, ...) error
- func (o *OnlineClient) DoJSON(ctx context.Context, method, path string, body, out any) error
- func (o *OnlineClient) RetryRateLimited(ctx context.Context, op func() error) error
- type OperationKind
- type OperationMode
- type PlaySyncInfo
- type RefusedSessions
- type RemoteBackupInfo
- type RemoteBackupSourceDevice
- type RemoteListInfo
- type RemoteRestoreInfo
- type RemoteRunInfo
- type RestoreInfo
Constants ¶
const ( CategoryZaparoo = "zaparoo" CategorySettings = "settings" CategoryInputs = "inputs" CategorySaves = "saves" CategorySavestates = "savestates" StatusNever = "never" StatusRunning = "running" StatusSuccess = "success" StatusPartial = "partial" StatusFailed = "failed" IntegrityUnchecked = "unchecked" IntegrityValid = "valid" RemoteAvailabilityUnknown = "unknown" RemoteAvailabilityAvailable = "available" )
const ( OperationLocalCreate = backupcoordinator.OperationLocalCreate OperationLocalInspect = backupcoordinator.OperationLocalInspect OperationLocalDelete = backupcoordinator.OperationLocalDelete OperationLocalRestore = backupcoordinator.OperationLocalRestore OperationRemoteUpload = backupcoordinator.OperationRemoteUpload OperationRemoteRestore = backupcoordinator.OperationRemoteRestore OperationRecovery = backupcoordinator.OperationRecovery OperationRead = backupcoordinator.OperationRead OperationWrite = backupcoordinator.OperationWrite )
const ( RemoteBackupTypeManual = "manual" RemoteBackupTypeScheduled = "scheduled" )
Remote snapshot types accepted by the server for Core-initiated commits.
Variables ¶
var ( ErrRestoreMediaActive = errors.New("cannot restore backup while media is active") ErrRestoreLaunchInProgress = errors.New("cannot restore backup while media is launching") ErrRestoreRecoveryNeeded = errors.New("backup restore rollback requires recovery") ErrRestoreJournalConflict = errors.New("a pending backup restore transaction exists") )
var ErrCoordinatorStopped = backupcoordinator.ErrStopped
Functions ¶
func HeartbeatCapabilities ¶ added in v2.18.0
HeartbeatCapabilities is the capability document every heartbeat carries: what this Core can do for the linked account, and which optional features the user has turned on.
func IsPlaySyncDisabledError ¶
IsPlaySyncDisabledError reports an expected opt-out or mid-sync disable. Background schedulers use this to keep intentional inactivity quiet while surfacing real upload failures at warning level.
func IsRateLimitedError ¶ added in v2.18.0
IsRateLimitedError reports a request the server kept refusing with a rate limit after every retry.
func IsRemoteUnlinkedError ¶
IsRemoteUnlinkedError reports expected inactivity when no usable online credential exists. Background schedulers use this to avoid warning on devices that have intentionally never linked or have since unlinked.
func LibrarySyncCapability ¶ added in v2.18.0
LibrarySyncCapability is the library_sync entry of the heartbeat capability document. It is always reported, with enabled false while the user has not opted in, so the account can tell a device that turned Library sync off from one whose Core does not support it.
func RemoteAvailabilityNeedsRefresh ¶
func RemoteAvailabilityNeedsRefresh(now time.Time, status *models.BackupStatusEntry) bool
Types ¶
type APIError ¶ added in v2.18.0
type APIError struct {
// Fields names the request fields a validation error refused, as the
// server rendered them. Empty for errors that name none.
Fields map[string]string
Code string
Message string
Status int
// contains filtered or unexported fields
}
APIError is an error response from a Zaparoo Online endpoint. Code is the machine-readable error code when the response carried one. A code that backup handles itself also matches that sentinel through errors.Is, and reads as it always has.
func AsAPIError ¶ added in v2.18.0
AsAPIError returns the API error response err carries, if any.
type BusyError ¶
type BusyError = backupcoordinator.BusyError
type Coordinator ¶
type Coordinator = backupcoordinator.Coordinator
func NewCoordinator ¶
func NewCoordinator() *Coordinator
type Info ¶
type Info struct {
CreatedAt time.Time `json:"createdAt"`
Categories map[string]models.BackupCategoryStatus `json:"categories,omitempty"`
Name string `json:"name"`
Path string `json:"path,omitempty"`
Status string `json:"status"`
Integrity string `json:"integrity"`
Error string `json:"error,omitempty"`
Warnings []models.BackupWarning `json:"warnings,omitempty"`
Size int64 `json:"size"`
}
type Lease ¶
type Lease = backupcoordinator.Lease
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
func NewManager ¶
func (*Manager) ListRemote ¶
func (m *Manager) ListRemote(ctx context.Context) (RemoteListInfo, error)
func (*Manager) MarkRemoteLinked ¶
func (m *Manager) MarkRemoteLinked()
MarkRemoteLinked clears a persisted unlinked marker after a successful claim/link, so the status UI reflects the fresh credential immediately.
func (*Manager) MarkRemoteUnlinked ¶
func (m *Manager) MarkRemoteUnlinked()
MarkRemoteUnlinked records that no valid remote credential exists (the token was revoked server-side or removed by logout), so the status UI prompts a re-link and the scheduler stops attempting remote backups.
func (*Manager) NewOnlineClient ¶ added in v2.18.0
func (m *Manager) NewOnlineClient(baseURL string) (*OnlineClient, error)
NewOnlineClient returns a client for the endpoint at baseURL. It fails with an error matching IsRemoteUnlinkedError when the device holds no credential for that endpoint, and a 401 response fails the same way.
func (*Manager) NotifyScheduleStale ¶
func (m *Manager) NotifyScheduleStale()
NotifyScheduleStale posts the deduplicated overdue-backup inbox notice.
func (*Manager) RecoverInterruptedRuns ¶
func (m *Manager) RecoverInterruptedRuns()
RecoverInterruptedRuns converts a persisted "running" status left behind by an interrupted run (power loss, hard shutdown) into a failure. The coordinator lease is in-memory, so at service startup no run can actually be in flight: a lingering "running" is always stale. Recording it as failed makes the scheduler retry on the short failure interval instead of waiting out the full daily/weekly cadence.
func (*Manager) RefreshRemoteAvailability ¶
func (*Manager) RefreshRemoteAvailabilityIfStale ¶
func (*Manager) RefreshRemoteAvailabilityIfStaleAsync ¶
func (m *Manager) RefreshRemoteAvailabilityIfStaleAsync()
RefreshRemoteAvailabilityIfStaleAsync refreshes remote availability in the background when the cached value is past its TTL, so status requests return immediately instead of blocking on a network round trip.
func (*Manager) RestoreRemote ¶
func (*Manager) RevokeRemoteLink ¶
RevokeRemoteLink invalidates the current device on the backup server before Core removes its local bearer. An already-missing or revoked credential is treated as success so local cleanup can finish.
func (*Manager) SendCapabilityHeartbeat ¶ added in v2.17.0
SendCapabilityHeartbeat reports liveness and the complete capability document without coupling callers to backup entitlement checks.
func (*Manager) SendHeartbeat ¶
SendHeartbeat reports liveness (Core version + capabilities) when the device is linked. Callers use it independently of backup runs so "last seen" stays fresh even with remote backup disabled.
func (*Manager) Status ¶
func (m *Manager) Status() models.BackupStatusResponse
func (*Manager) SyncPlayHistory ¶
func (m *Manager) SyncPlayHistory(ctx context.Context) (PlaySyncInfo, error)
SyncPlayHistory uploads every session updated since the server's watermark. The first call after linking is the bulk import of the whole local history; afterwards each pass sends only what changed. A pass is cheap when nothing changed: one watermark GET and one empty local query.
func (*Manager) TrackScheduleStale ¶
TrackScheduleStale maintains the persisted record of when remote backup scheduling became active and reports whether scheduled backups are stale: scheduling active for at least staleAfter with no successful run inside that window. Staleness is only judged against a reliable clock.
func (*Manager) WithActiveMedia ¶
func (m *Manager) WithActiveMedia(activeMedia func() *models.ActiveMedia) *Manager
func (*Manager) WithCoordinator ¶
func (m *Manager) WithCoordinator(coordinator *Coordinator) *Manager
func (*Manager) WithPauser ¶
WithPauser subjects backup work to the shared media pause/throttle policy: file collection, hashing, packing, and uploads checkpoint on the pauser so they yield to a running game the same way media indexing does. A nil pauser (the default) leaves backups unthrottled.
func (*Manager) WithRateLimitWaits ¶ added in v2.18.0
WithRateLimitWaits overrides how long rate-limited requests wait before a retry, for tests that exercise the retry path.
func (*Manager) WithRefusedSessions ¶ added in v2.18.0
func (m *Manager) WithRefusedSessions(refused *RefusedSessions) *Manager
WithRefusedSessions shares a process-lifetime record of play sessions the account refused, so a pass skips the ones already known.
type Manifest ¶
type Manifest struct {
CreatedAt time.Time `json:"createdAt"`
Categories map[string]models.BackupCategoryStatus `json:"categories"`
Warnings []models.BackupWarning `json:"warnings,omitempty"`
Platform string `json:"platform"`
CoreVersion string `json:"coreVersion"`
Files []FileRef `json:"files"`
Version int `json:"version"`
}
type OnlineClient ¶ added in v2.18.0
type OnlineClient struct {
// contains filtered or unexported fields
}
OnlineClient sends authenticated device requests to a Zaparoo Online endpoint for features other than backup. It shares the backup client's credential lookup, device headers, per-request timeouts and rate-limit handling, so every Online feature behaves the same on the wire.
func (*OnlineClient) BaseURL ¶ added in v2.18.0
func (o *OnlineClient) BaseURL() string
BaseURL returns the endpoint the client talks to, without a trailing slash.
func (*OnlineClient) CredentialTag ¶ added in v2.18.0
func (o *OnlineClient) CredentialTag() string
CredentialTag returns a short digest of the device credential, so sync bookkeeping can tell that the device was linked again since it last synced without keeping the credential itself.
func (*OnlineClient) DoBytes ¶ added in v2.18.0
func (o *OnlineClient) DoBytes( ctx context.Context, method, path string, body []byte, headers http.Header, out any, ) error
DoBytes sends body as application/octet-stream with the extra headers, and decodes a successful JSON response into out unless out is nil.
func (*OnlineClient) DoJSON ¶ added in v2.18.0
DoJSON sends body encoded as JSON, or no body when it is nil, and decodes a successful JSON response into out unless out is nil. path may end in a query string.
func (*OnlineClient) RetryRateLimited ¶ added in v2.18.0
func (o *OnlineClient) RetryRateLimited(ctx context.Context, op func() error) error
RetryRateLimited runs op, waiting out and retrying rate-limited responses. The wait honours the server's Retry-After within the client's bounds.
type OperationKind ¶
type OperationKind = backupcoordinator.OperationKind
type OperationMode ¶
type OperationMode = backupcoordinator.OperationMode
type PlaySyncInfo ¶
type PlaySyncInfo struct {
Uploaded int
Batches int
// Refused counts sessions the account would not accept. They are worked
// around rather than retried forever, and reported so they can be
// repaired.
Refused int
// NewlyRefused counts the refusals this process had not seen before. Only
// these are worth telling the user about again.
NewlyRefused int
}
PlaySyncInfo summarizes one play-history sync pass.
type RefusedSessions ¶ added in v2.18.0
type RefusedSessions struct {
// contains filtered or unexported fields
}
RefusedSessions remembers the play sessions the account has refused, for as long as the process runs.
A refused session is never marked synced, so without this every pass sent it again, was refused again, spent up to nine extra requests finding it again, and raised the same inbox warning again. It is deliberately not persisted: a restart retries each one once, which is how a session repaired locally or a rule relaxed on the server gets through. A session edited since it was refused has a new UpdatedAt, so it is retried straight away.
The scheduler builds a fresh Manager for every pass, so this lives outside it and is handed in.
func NewRefusedSessions ¶ added in v2.18.0
func NewRefusedSessions() *RefusedSessions
NewRefusedSessions returns an empty set.
type RemoteBackupInfo ¶
type RemoteBackupInfo struct {
CoreVersion *string `json:"coreVersion,omitempty"`
Platform *string `json:"platform,omitempty"`
VerifiedAt *time.Time `json:"verifiedAt,omitempty"`
RestoredAt *time.Time `json:"restoredAt,omitempty"`
SourceDevice *RemoteBackupSourceDevice `json:"sourceDevice,omitempty"`
Categories map[string]remoteCategorySummary `json:"categories"`
ManifestHash string `json:"manifestHash"`
BackupType string `json:"backupType"`
CreatedAt time.Time `json:"createdAt"`
Manifest json.RawMessage `json:"manifest,omitempty"`
ID string `json:"id"`
SchemaVersion int `json:"schemaVersion"`
SizeBytes int64 `json:"sizeBytes"`
// Incompatible marks snapshots committed with a newer schema version
// than this Core supports: they list fine but refuse to restore.
Incompatible bool `json:"incompatible,omitempty"`
}
RemoteBackupInfo is remote snapshot metadata returned to Core clients.
type RemoteBackupSourceDevice ¶
type RemoteBackupSourceDevice struct {
Platform *string `json:"platform,omitempty"`
ID string `json:"id"`
Name string `json:"name"`
Linked bool `json:"linked"`
Current bool `json:"current"`
}
RemoteBackupSourceDevice identifies the account device that created a snapshot. Current is relative to the device requesting the catalog.
type RemoteListInfo ¶
type RemoteListInfo struct {
Items []RemoteBackupInfo `json:"items"`
StorageUsedBytes int64 `json:"storageUsedBytes"`
StorageQuotaBytes int64 `json:"storageQuotaBytes"`
}
RemoteListInfo contains remote backups and quota usage.
type RemoteRestoreInfo ¶
type RemoteRestoreInfo struct {
PreRestoreBackup *Info `json:"preRestoreBackup,omitempty"`
RestoredFrom RemoteBackupInfo `json:"restoredFrom"`
}
RemoteRestoreInfo describes one completed remote restore.
type RemoteRunInfo ¶
type RemoteRunInfo struct {
Backup RemoteBackupInfo `json:"backup"`
Categories map[string]remoteCategorySummary `json:"categories"`
Warnings []models.BackupWarning `json:"warnings,omitempty"`
UploadedFiles int `json:"uploadedFiles"`
DedupedFiles int `json:"dedupedFiles"`
SkippedFiles int `json:"skippedFiles,omitempty"`
UploadedPacks int `json:"uploadedPacks"`
UploadedBytes int64 `json:"uploadedBytes"`
StorageUsedBytes int64 `json:"storageUsedBytes,omitempty"`
StorageQuotaBytes int64 `json:"storageQuotaBytes,omitempty"`
// NoChanges marks a run whose manifest matched the server's existing
// snapshot: the run succeeded and the content is verified stored, but
// nothing new was uploaded and no new snapshot record was created.
NoChanges bool `json:"noChanges,omitempty"`
}
RemoteRunInfo describes one completed remote backup run.