Documentation
¶
Overview ¶
Package launcher manages the optional OS-backed worker launcher.
Index ¶
- Constants
- Variables
- func Delete(path string) error
- func EnsureFreshBinary(ctx context.Context) (bool, error)
- func IsEnabled() bool
- func Kickstart(ctx context.Context, target string) error
- func List(repoRoot string) ([]string, error)
- func MarkerPath(repoRoot, checkpointID string) string
- func PendingDir(repoRoot string) string
- func SettingsPath() (string, error)
- func TimerPath() (string, error)
- func TimerTarget() string
- func UnitPath() (string, error)
- func UnitTarget() string
- func UserDomain() string
- func WorkerLogPath() (string, error)
- func Write(m Marker) error
- func WriteSettings(s UserSettings) error
- type BinaryIdentity
- type DisableResult
- type InstallResult
- type LauncherSettings
- type Marker
- type RefreshResult
- type ServiceHealth
- type StatusResult
- type UserSettings
Constants ¶
const LabelWorker = "sh.semantica.worker"
LabelWorker is the worker service label, used as the launchd plist label, the systemd unit base name, and the Task Scheduler task name. Same identifier across all backends so diagnostics stay consistent.
Variables ¶
var ErrUnsupportedOS = errors.New("launcher: unsupported OS")
ErrUnsupportedOS reports that the launcher has no backend on the current OS.
Functions ¶
func EnsureFreshBinary ¶ added in v0.6.0
EnsureFreshBinary checks the registered binary's identity and refreshes the launcher when it is stale. Returns whether a refresh ran. The dispatch path calls this so a binary replacement self-heals on the next commit.
func IsEnabled ¶
func IsEnabled() bool
IsEnabled reports whether the launcher is enabled. Read errors fall back to false so hook-side callers do not break commits.
func Kickstart ¶
Kickstart triggers an on-demand activation of the worker unit. The target argument is the systemd unit name; honors the caller-supplied target rather than deriving its own so callers retain control over which unit is started.
func List ¶
List returns committed marker paths in lexical order. A missing directory is treated as empty.
func MarkerPath ¶
MarkerPath returns the canonical marker path.
func PendingDir ¶
PendingDir returns <repoRoot>/.semantica/pending.
func SettingsPath ¶
SettingsPath returns the launcher settings path. It honors SEMANTICA_HOME via broker.GlobalBase.
func TimerPath ¶ added in v0.6.0
TimerPath returns the systemd user timer path for the periodic worker drain.
func TimerTarget ¶ added in v0.6.0
func TimerTarget() string
TimerTarget returns the systemd timer unit name.
func UnitPath ¶ added in v0.3.7
UnitPath returns the systemd user unit path for the worker. Honors XDG_CONFIG_HOME via os.UserConfigDir; falls back to $HOME/.config when XDG_CONFIG_HOME is unset.
func UnitTarget ¶ added in v0.3.7
func UnitTarget() string
UnitTarget returns the systemd unit name. systemctl --user accepts this string as the unit argument.
func UserDomain ¶
func UserDomain() string
UserDomain returns the empty string on Linux. The systemd user instance has no analog to launchctl's gui/<uid> tuple; the systemctl --user invocation is the access point.
func WorkerLogPath ¶
WorkerLogPath returns the launcher worker log path. Cross-platform.
func WriteSettings ¶
func WriteSettings(s UserSettings) error
WriteSettings atomically writes the user-level settings file.
Types ¶
type BinaryIdentity ¶ added in v0.6.0
type BinaryIdentity struct {
Path string
Size int64
ModMS int64 // modification time, Unix milliseconds
}
BinaryIdentity is a cheap fingerprint of the binary registered with the launcher. Size plus modification time changes on normal upgrades and local installs, which is enough to detect when the service should be re-registered before the next kick.
func StatBinaryIdentity ¶ added in v0.6.0
func StatBinaryIdentity(path string) (BinaryIdentity, error)
StatBinaryIdentity reads the current identity of the binary at path.
type DisableResult ¶
type DisableResult struct {
// WasEnabled reflects the settings flag prior to disable.
WasEnabled bool
// RemovedUnitPath is the unit/plist/task path that was
// removed, if any. Empty when no file was on disk.
RemovedUnitPath string
// Warnings lists cleanup steps that did not complete (for
// example a periodic timer that could not be disabled). The
// disable still succeeds; callers should surface these.
Warnings []string
}
DisableResult describes the outcome of a Disable call.
type InstallResult ¶
type InstallResult struct {
// UnitPath is the installed unit/plist/task path.
UnitPath string
// UnitTarget is the OS-specific service identifier.
UnitTarget string
// Reinstalled reports whether a previous service was already
// loaded at the time of install.
Reinstalled bool
}
InstallResult describes a successful Enable or reinstall.
func Enable ¶
func Enable(ctx context.Context, binaryPath string) (*InstallResult, error)
Enable installs the worker, registers it with the OS daemon manager, and records the enabled state in user settings. The OS-specific work runs through the active manager backend; on platforms without one, this returns ErrUnsupportedOS.
The backend check runs before binary-path validation so the "unsupported OS" contract holds for callers that use errors.Is(err, ErrUnsupportedOS): a non-darwin host returns ErrUnsupportedOS regardless of whether the supplied path is absolute or exists.
type LauncherSettings ¶
type LauncherSettings struct {
// Enabled reports whether the launcher is enabled.
Enabled bool `json:"enabled"`
// InstalledUnitPath is the launcher install path written by
// Enable. The JSON tag is "installed_unit_path"; the legacy
// "installed_plist_path" key is handled by the dual-key
// MarshalJSON / UnmarshalJSON below.
InstalledUnitPath string `json:"installed_unit_path,omitempty"`
// InstalledAt is the enable-time Unix millisecond timestamp.
InstalledAt int64 `json:"installed_at,omitempty"`
// InstalledBinaryPath is the binary path the OS daemon manager was
// bound to at enable time.
InstalledBinaryPath string `json:"installed_binary_path,omitempty"`
// InstalledBinarySize and InstalledBinaryModMS fingerprint that
// binary so dispatch can detect in-place replacement (which leaves
// launchd holding stale code-signing state) and self-heal via
// Refresh.
InstalledBinarySize int64 `json:"installed_binary_size,omitempty"`
InstalledBinaryModMS int64 `json:"installed_binary_mod_ms,omitempty"`
}
LauncherSettings records the launcher's installed state.
The canonical on-disk install-path key is "installed_unit_path". During the transition, the legacy "installed_plist_path" key is also written with the same value, and the read path accepts either key.
func (LauncherSettings) MarshalJSON ¶ added in v0.3.7
func (s LauncherSettings) MarshalJSON() ([]byte, error)
MarshalJSON writes both install-path keys with the same value while the legacy key is still supported.
func (LauncherSettings) RecordedIdentity ¶ added in v0.6.0
func (s LauncherSettings) RecordedIdentity() (BinaryIdentity, bool)
RecordedIdentity returns the identity captured at enable time, and whether one was recorded. Settings written by older versions carry no identity; callers treat that as stale so one refresh migrates them.
func (*LauncherSettings) UnmarshalJSON ¶ added in v0.3.7
func (s *LauncherSettings) UnmarshalJSON(data []byte) error
UnmarshalJSON reads both install-path keys and prefers installed_unit_path when it is present, even if it is the empty string. A nil pointer means the key was absent or null, so the legacy installed_plist_path fallback applies.
Conflicting non-empty values resolve to the canonical key. The next WriteSettings overwrites both keys with the canonical value, so the conflict cannot persist past one read/write cycle.
type Marker ¶
type Marker struct {
// CheckpointID also becomes the filename stem.
CheckpointID string `json:"checkpoint_id"`
// CommitHash is the linked commit.
CommitHash string `json:"commit_hash"`
// RepoRoot is the absolute repository path.
RepoRoot string `json:"repo_root"`
// WrittenAt is the hook-side Unix millisecond timestamp.
WrittenAt int64 `json:"written_at"`
}
Marker is the handoff written by the hook and read by the drain command.
func Read ¶
Read loads and validates one marker. Use ReadInQueue when the caller discovered the file from a specific queue directory.
func ReadInQueue ¶
ReadInQueue loads a marker and checks that it matches the queue it came from.
type RefreshResult ¶ added in v0.6.0
type RefreshResult struct {
// Enabled is false when the launcher is not enabled; Refresh is a
// no-op in that case.
Enabled bool
// BinaryPath is the binary the launcher was re-bound to.
BinaryPath string
// Install carries the re-install result when Enabled.
Install *InstallResult
}
RefreshResult reports what Refresh did.
func Refresh ¶ added in v0.6.0
func Refresh(ctx context.Context) (*RefreshResult, error)
Refresh re-binds the OS daemon manager to the currently executing binary. It is a no-op when the launcher is disabled, and a full re-enable when it is enabled.
The target is always os.Executable(), never the path recorded in settings: installer hooks invoke the freshly installed binary, so preferring the recorded path would re-bind launchd to a stale install location after a user migrates (Homebrew to curl, custom INSTALL_DIR), and then stamp a fresh identity on the old binary, making status look healthy while the launcher runs the wrong build.
Refresh deliberately does not kickstart; callers decide whether to kick (the CLI command does, to drain queued markers).
type ServiceHealth ¶ added in v0.6.0
type ServiceHealth struct {
// LastExitReason is the daemon's recorded last exit reason, when
// exposed (e.g. launchd's OS_REASON_CODESIGNING).
LastExitReason string
// NeedsLWCRUpdate reports launchd's "needs LWCR update" property:
// the pinned code requirement no longer matches the binary.
NeedsLWCRUpdate bool
// SpawnRefused reports that the service is registered but the OS
// daemon manager is refusing to run it.
SpawnRefused bool
}
ServiceHealth is the OS daemon manager's spawn-health view of the worker service.
type StatusResult ¶
type StatusResult struct {
// OS is the runtime.GOOS value at the time of the call.
OS string
// SettingsEnabled is the launcher.enabled flag from settings.json.
SettingsEnabled bool
// InstalledUnitPath is the unit/plist/task path recorded in
// settings.
InstalledUnitPath string
// InstalledAt is the enable-time Unix millisecond timestamp.
InstalledAt int64
// SettingsError is set when the settings file exists but could
// not be read cleanly.
SettingsError string
// ExpectedUnitPath is the canonical unit/plist/task path for
// the current user.
ExpectedUnitPath string
// UnitOnDisk reports whether the unit/plist/task file exists
// at the recorded or expected path.
UnitOnDisk bool
// UnitTarget is the OS-specific service identifier.
UnitTarget string
// LoadedInDaemon reports whether the OS daemon manager has the
// service registered.
LoadedInDaemon bool
// ServiceState is a short summary of what the OS daemon manager
// reported:
// - "loaded" : service is registered
// - "not loaded" : service is not registered
// - "unsupported" : no launcher backend on this OS
// - "error: <msg>" : daemon-manager call failed
ServiceState string
// LogPath is the launcher worker log path.
LogPath string
// Health carries OS-specific daemon spawn-health signals.
Health ServiceHealth
// BinaryStale reports that the registered binary no longer matches
// the identity recorded at enable time; BinaryStaleReason explains.
// Remediation for both this and Health.SpawnRefused is
// `semantica launcher refresh`.
BinaryStale bool
BinaryStaleReason string
}
StatusResult describes launcher state as reported by settings, the unit/plist/task file on disk, and the OS daemon manager.
type UserSettings ¶
type UserSettings struct {
Launcher LauncherSettings `json:"launcher,omitempty"`
}
UserSettings is the user-level settings file at $HOME/.semantica/settings.json.
func ReadSettings ¶
func ReadSettings() (UserSettings, error)
ReadSettings loads the user-level settings file. A missing file returns the zero value. A malformed file returns an error.