state

package
v2.17.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 31, 2026 License: GPL-3.0 Imports: 16 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// RemoteStateUnknown means the poller has not reported yet.
	RemoteStateUnknown = "unknown"
	// RemoteStateDisabled means the owner has not enabled remote control.
	RemoteStateDisabled = "disabled"
	// RemoteStateUnlinked means there is no linked-account credential.
	RemoteStateUnlinked = "unlinked"
	// RemoteStateConnecting means the capability is being advertised.
	RemoteStateConnecting = "connecting"
	// RemoteStateWaiting means the device is polling for commands normally.
	RemoteStateWaiting = "waiting"
	// RemoteStateNotRemoteDevice means the server refused the poll because
	// this device is not the account's designated remote device.
	RemoteStateNotRemoteDevice = "not_remote_device"
	// RemoteStateUnavailable means the server reports the feature as off.
	RemoteStateUnavailable = "unavailable"
	// RemoteStateCredentialRejected means the server rejected the device
	// credential; the account must be linked again.
	RemoteStateCredentialRejected = "credential_rejected" //nolint:gosec // G101: a state name, not a credential
	// RemoteStateError means the last poll failed for another reason (no
	// network, a server error, rate limiting).
	RemoteStateError = "error"
)

Remote control states, as last observed by the remote operations poller. They describe why the device is or isn't reachable for remote commands right now, so the owner can see the difference between "waiting for a command" and "the server won't talk to this device".

Variables

View Source
var (
	ErrNoActiveMedia          = errors.New("no active media")
	ErrActiveMediaChanged     = errors.New("active media changed")
	ErrRestoreInProgress      = errors.New("backup restore is in progress")
	ErrMediaLaunchInProgress  = errors.New("media launch is in progress")
	ErrRestoreRestartRequired = errors.New("backup restore restart is pending")
)
View Source
var ErrInvalidNextAction = errors.New("invalid next-action command")

ErrInvalidNextAction is returned when a one-shot next-action command (launcher override or next-card write) fails validation.

View Source
var ErrLaunchBlockedByHook = errors.New("launch blocked by before_media_start hook")

ErrLaunchBlockedByHook is returned when the before_media_start hook rejects a launch.

View Source
var ErrLaunchInProgress = errors.New("launch already in progress")

ErrLaunchInProgress is returned when a launch is attempted while another is in progress.

View Source
var ErrLaunchRequiresProfile = errors.New("launch requires an active profile")

ErrLaunchRequiresProfile is returned when profiles.require_for_launch is set and no profile is active.

View Source
var ErrRunZapScriptDisabled = errors.New("run ZapScript is disabled")

ErrRunZapScriptDisabled is returned when ZapScript execution is attempted while the user has disabled it via settings.runZapScript. Every source (local scans, mappings, remote operations) is subject to this switch — there is no bypass.

Functions

This section is empty.

Types

type LauncherManager added in v2.7.0

type LauncherManager struct {
	// contains filtered or unexported fields
}

LauncherManager manages the lifecycle of launcher contexts across the application. It provides thread-safe access to a shared context that gets canceled whenever a new launcher starts, allowing previous launcher cleanup routines to detect when they've been superseded and should skip their cleanup actions.

func NewLauncherManager added in v2.7.0

func NewLauncherManager() *LauncherManager

func (*LauncherManager) EndLaunch added in v2.8.0

func (lm *LauncherManager) EndLaunch()

EndLaunch releases the launch lock.

func (*LauncherManager) GetContext added in v2.7.0

func (lm *LauncherManager) GetContext() context.Context

GetContext returns the current launcher context. This context will be canceled when a new launcher starts.

func (*LauncherManager) NewContext added in v2.7.0

func (lm *LauncherManager) NewContext() context.Context

NewContext cancels the current launcher context and creates a new one. This should be called when starting a new launcher to invalidate any cleanup routines from previous launchers. Returns the newly created context.

func (*LauncherManager) TryStartLaunch added in v2.8.0

func (lm *LauncherManager) TryStartLaunch() error

TryStartLaunch attempts to acquire the launch lock. Returns ErrLaunchInProgress if a launch is already in progress.

type PendingLaunchOverride added in v2.13.0

type PendingLaunchOverride struct {
	Source     tokens.Token
	CreatedAt  time.Time
	LauncherID string
}

State holds the runtime state of the Zaparoo service.

LOCKING RULES: The mu mutex protects all mutable fields. To prevent deadlocks:

  • Never send to channels while holding the lock (notifications, callbacks)
  • Never call external methods (reader.OnMediaChange, hooks) while holding the lock
  • Pattern: lock → modify state → copy needed data → unlock → send notifications

See SetActiveCard, SetActiveMedia, SetReader, RemoveReader for examples.

type PendingWrite added in v2.13.0

type PendingWrite struct {
	Source    tokens.Token
	CreatedAt time.Time
	Payload   string
}

type RemoteStatus added in v2.17.0

type RemoteStatus struct {
	LastContactAt time.Time
	UpdatedAt     time.Time
	State         string
	LastErrorCode string
}

RemoteStatus is the poller's last observation. LastContactAt is the last time the server answered a poll normally; LastErrorCode is the server's error code (or a short local one) for the states that carry one.

type State

type State struct {
	Notifications chan<- models.Notification
	// contains filtered or unexported fields
}

func NewState

func NewState(platform platforms.Platform, bootUUID string) (state *State, notificationCh <-chan models.Notification)

func (*State) AcquireMediaLaunch added in v2.16.0

func (s *State) AcquireMediaLaunch() (platforms.MediaLaunchAccess, error)

func (*State) AcquireMediaStop added in v2.16.1

func (s *State) AcquireMediaStop(ctx context.Context) (func(), error)

AcquireMediaStop waits for in-flight media launches, then prevents another launch from starting until the returned release function is called.

func (*State) AcquireRestoreAccess added in v2.16.0

func (s *State) AcquireRestoreAccess() (func(), error)

func (*State) AcquireUpdateMediaGate added in v2.17.0

func (s *State) AcquireUpdateMediaGate(ctx context.Context) (func(), error)

AcquireUpdateMediaGate waits for in-flight launches and ActiveMedia publications, then prevents either from starting until release. The updater holds this gate from its final safety check through restart cancellation.

func (*State) ActiveMedia

func (s *State) ActiveMedia() *models.ActiveMedia

func (*State) ActiveMediaReady added in v2.14.0

func (s *State) ActiveMediaReady() bool

func (*State) ActiveMediaReadyGeneration added in v2.14.0

func (s *State) ActiveMediaReadyGeneration() (uint64, bool)

func (*State) ActiveMediaReplacedSince added in v2.17.0

func (s *State) ActiveMediaReplacedSince(gen uint64, hadMedia bool) bool

ActiveMediaReplacedSince reports whether the active media changed since gen was captured alongside hadMedia. It is how a caller that ran before_exit tells that the hook launched or stopped media itself: stopping after that would kill what the hook started rather than the media the caller set out to exit. With nothing active when gen was taken, before_exit is a no-op and there is nothing it could have replaced.

The generation tracks media identity, not launches, so a before_exit script that relaunches media comparing equal to the outgoing media (ActiveMedia.Equal: same slot, system and slugified name) does not read as a replacement, and the caller's stop goes ahead. That is correct: media with the same content is the same media, so the caller is still stopping exactly what it asked to stop. Only a launch of something genuinely different needs protecting from the stop.

func (*State) ActiveProfile added in v2.16.0

func (s *State) ActiveProfile() *models.ActiveProfile

ActiveProfile returns a copy of the device's active profile snapshot, or nil when no profile is active.

func (*State) AnyReaderWriteActive added in v2.17.0

func (s *State) AnyReaderWriteActive() bool

AnyReaderWriteActive reports whether any reader is part-way through writing a token.

ReaderWriteActive answers for one reader and defaults to the empty ID, which no production caller records under: writes are tracked per reader by Reader.ID(). A caller that wants to know whether the device is mid-write at all — the updater, before it restarts the service — has to ask about every reader, not about a reader that does not exist.

func (*State) BackgroundAutoPaused added in v2.15.0

func (s *State) BackgroundAutoPaused() bool

func (*State) BackgroundMedia added in v2.15.0

func (s *State) BackgroundMedia() *models.ActiveMedia

func (*State) BackupCoordinator added in v2.16.0

func (s *State) BackupCoordinator() *backupcoordinator.Coordinator

func (*State) BeginRestoreGate added in v2.16.0

func (s *State) BeginRestoreGate() (func(bool), error)

func (*State) BootUUID added in v2.7.0

func (s *State) BootUUID() string

func (*State) ClearPendingWrite added in v2.13.0

func (s *State) ClearPendingWrite()

func (*State) ConsumePendingLaunchOverride added in v2.13.0

func (s *State) ConsumePendingLaunchOverride() *PendingLaunchOverride

func (*State) ConsumePendingWrite added in v2.13.0

func (s *State) ConsumePendingWrite() *PendingWrite

func (*State) GetActiveCard

func (s *State) GetActiveCard() tokens.Token

func (*State) GetActivePlaylist

func (s *State) GetActivePlaylist() *playlists.Playlist

func (*State) GetBackgroundPlaylist added in v2.15.0

func (s *State) GetBackgroundPlaylist() *playlists.Playlist

func (*State) GetContext

func (s *State) GetContext() context.Context

func (*State) GetLastScanned

func (s *State) GetLastScanned() tokens.Token

func (*State) GetPendingLaunchOverride added in v2.13.0

func (s *State) GetPendingLaunchOverride() *PendingLaunchOverride

func (*State) GetPendingWrite added in v2.13.0

func (s *State) GetPendingWrite() *PendingWrite

func (*State) GetReader

func (s *State) GetReader(readerID string) (readers.Reader, bool)

GetReader returns the Reader for a given ReaderID.

func (*State) GetSoftwareToken

func (s *State) GetSoftwareToken() *tokens.Token

func (*State) GetWroteToken

func (s *State) GetWroteToken(readerIDs ...string) *tokens.Token

func (*State) Inbox added in v2.8.0

func (s *State) Inbox() *inbox.Service

Inbox returns the inbox service for adding system notifications.

func (*State) LauncherManager added in v2.7.0

func (s *State) LauncherManager() *LauncherManager

func (*State) ListReaders

func (s *State) ListReaders() []readers.Reader

ListReaders returns all registered Reader instances.

func (*State) MarkActiveMediaReady added in v2.14.0

func (s *State) MarkActiveMediaReady(gen uint64)

func (*State) MarkWrittenTagRemoved added in v2.17.0

func (s *State) MarkWrittenTagRemoved(readerIDs ...string)

func (*State) MediaDBRecoveryActive added in v2.17.0

func (s *State) MediaDBRecoveryActive() bool

MediaDBRecoveryActive reports whether automatic media database recovery is currently running.

func (*State) ReaderWriteActive added in v2.17.0

func (s *State) ReaderWriteActive(readerIDs ...string) bool

func (*State) RemoteStatus added in v2.17.0

func (s *State) RemoteStatus() RemoteStatus

RemoteStatus returns the poller's last observation. State is empty until the poller has reported once.

func (*State) RemoveReader

func (s *State) RemoveReader(readerID string)

RemoveReader removes a reader by its ReaderID and closes it.

func (*State) RestartRequested added in v2.10.0

func (s *State) RestartRequested() bool

RestartRequested returns true if the service shutdown was triggered by a restart request (e.g. after applying an update).

func (*State) RestartService added in v2.10.0

func (s *State) RestartService()

RestartService signals the service to shut down and restart with the new binary. Used after applying an update for graceful restart instead of os.Exit.

func (*State) RunBeforeExitHook added in v2.17.0

func (s *State) RunBeforeExitHook()

RunBeforeExitHook invokes the registered before_exit callback synchronously in the caller's goroutine. It is a no-op when no hook is registered or when another before_exit run is already in flight: at most one before_exit script runs process-wide at a time, so a script that itself stops or launches media cannot re-enter this path from any goroutine.

Callers must not hold a media gate (AcquireMediaStop, AcquireUpdateMediaGate) when calling this. The hook script may launch media, which takes the read side of the same gate and would deadlock against the exclusive holder.

func (*State) RunZapScriptEnabled

func (s *State) RunZapScriptEnabled() bool

func (*State) SetActiveCard

func (s *State) SetActiveCard(card tokens.Token)

func (*State) SetActiveMedia

func (s *State) SetActiveMedia(media *models.ActiveMedia)

func (*State) SetActivePlaylist

func (s *State) SetActivePlaylist(playlist *playlists.Playlist)

func (*State) SetActiveProfile added in v2.16.0

func (s *State) SetActiveProfile(profile *models.ActiveProfile)

SetActiveProfile sets or clears (nil) the device's active profile and broadcasts a profiles.active notification. The snapshot is stored by value internally so callers cannot mutate state through the pointer.

func (*State) SetBackgroundAutoPaused added in v2.15.0

func (s *State) SetBackgroundAutoPaused(v bool)

func (*State) SetBackgroundMedia added in v2.15.0

func (s *State) SetBackgroundMedia(media *models.ActiveMedia)

func (*State) SetBackgroundPlaylist added in v2.15.0

func (s *State) SetBackgroundPlaylist(playlist *playlists.Playlist)

func (*State) SetBeforeExitHook added in v2.17.0

func (s *State) SetBeforeExitHook(hook func())

SetBeforeExitHook registers the callback run just before active media is stopped or replaced. Pass nil to clear it.

func (*State) SetInbox added in v2.8.0

func (s *State) SetInbox(svc *inbox.Service)

SetInbox sets the inbox service. Called during service startup after database is ready.

func (*State) SetMediaDBRecoveryActive added in v2.17.0

func (s *State) SetMediaDBRecoveryActive(active bool)

SetMediaDBRecoveryActive records whether automatic media database recovery currently owns the recovery workflow.

func (*State) SetOnMediaStartHook

func (s *State) SetOnMediaStartHook(hook func(*models.ActiveMedia, uint64))

func (*State) SetOnMediaStopHook added in v2.15.0

func (s *State) SetOnMediaStopHook(hook func())

func (*State) SetPendingLaunchOverride added in v2.13.0

func (s *State) SetPendingLaunchOverride(pending *PendingLaunchOverride)

func (*State) SetPendingWrite added in v2.13.0

func (s *State) SetPendingWrite(pending *PendingWrite)

func (*State) SetReader

func (s *State) SetReader(reader readers.Reader)

SetReader registers a reader using its ReaderID as the key. If a reader with the same ReaderID exists, it is closed first.

func (*State) SetReaderWriteActive added in v2.17.0

func (s *State) SetReaderWriteActive(active bool, readerIDs ...string)

func (*State) SetRemoteStatus added in v2.17.0

func (s *State) SetRemoteStatus(remoteState, errorCode string)

SetRemoteStatus records the poller's latest observation. A waiting state also counts as a successful contact.

func (*State) SetRunZapScript

func (s *State) SetRunZapScript(run bool)

func (*State) SetSoftwareToken

func (s *State) SetSoftwareToken(token *tokens.Token)

func (*State) SetUIEvents added in v2.16.0

func (s *State) SetUIEvents(service *uievents.Service)

SetUIEvents stores the process-wide UI event service.

func (*State) SetWroteToken

func (s *State) SetWroteToken(token *tokens.Token)

func (*State) SetWroteTokenForReader added in v2.17.0

func (s *State) SetWroteTokenForReader(readerID string, token *tokens.Token)

func (*State) StopService

func (s *State) StopService()

func (*State) TryAcquireRestoreAccess added in v2.16.0

func (s *State) TryAcquireRestoreAccess() (func(), error)

func (*State) UIEvents added in v2.16.0

func (s *State) UIEvents() *uievents.Service

UIEvents returns the process-wide UI event service.

func (*State) WaitForActiveMediaReady added in v2.14.0

func (s *State) WaitForActiveMediaReady(ctx context.Context, expectedGen uint64) error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL