updater

package
v0.2.5 Latest Latest
Warning

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

Go to latest
Published: May 18, 2026 License: MPL-2.0 Imports: 25 Imported by: 0

Documentation

Overview

Package updater implements a2ald self-update logic: periodic version checks, atomic binary replacement, startup-counter-based rollback, and retraction detection. See doc-local/a2ald 自动更新设计.md for the full design.

Index

Constants

View Source
const (
	StatusPending        = "pending"         // binary replaced, health not yet confirmed
	StatusOK             = "ok"              // new binary confirmed healthy
	StatusRolledBack     = "rolled_back"     // rollback executed, old binary restored
	StatusRollbackFailed = "rollback_failed" // terminal: .old unavailable/corrupt, no rollback possible
)

Status values stored in update_state.json.

Variables

This section is empty.

Functions

func CheckAndRollback

func CheckAndRollback(dataDir string)

CheckAndRollback must be called at the very start of main(), before daemon.New() acquires the data-dir lock. It implements the startup-counter rollback described in the design doc.

Guard chain (any failure → return, normal startup):

  1. No state file or unreadable
  2. Unknown schema
  3. Dev build (version.Version == "dev")
  4. state.NewVersion != version.Version ← prevents false triggers
  5. status != "pending"

If attempts reaches 3 and .old is valid, the rollback is executed and checkRollbackExitFn(0) runs (production: os.Exit) so the service manager restarts with the old binary.

func IsPersistentService

func IsPersistentService() bool

IsPersistentService reports whether a2ald is running under a service manager that will automatically restart it on failure.

Linux: systemd sets INVOCATION_ID (v232+) and JOURNAL_STREAM (v231+). macOS: launchd is PID 1 and does not set TERM for background agents. Other: always returns false.

func RunSmokeTest

func RunSmokeTest(dataDir string) error

RunSmokeTest validates config parsing, keys, and data-dir writeability without starting the daemon or acquiring the data-dir lock. Called when a2ald is invoked as "__smoke-test --data-dir <path>" by the updater.

func WriteState

func WriteState(dataDir string, s *UpdateState) error

WriteState atomically writes state via a temp file + rename.

Types

type UpdateState

type UpdateState struct {
	Schema            int       `json:"schema"`
	Status            string    `json:"status"`
	OldVersion        string    `json:"old_version"`
	NewVersion        string    `json:"new_version"`
	OldChecksumSHA256 string    `json:"old_checksum_sha256"`
	ReplacedAt        time.Time `json:"replaced_at"`
	Attempts          int       `json:"attempts"`
	LastAttemptAt     time.Time `json:"last_attempt_at,omitempty"`
	RolledBackAt      time.Time `json:"rolled_back_at,omitempty"`
}

UpdateState is persisted as <data-dir>/update_state.json. It is written atomically before os.Exit(0) and read at startup.

func ReadState

func ReadState(dataDir string) (*UpdateState, error)

ReadState reads update_state.json. Returns nil (no error) when file is absent.

type Updater

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

Updater manages periodic update checks, binary replacement, and the post-update health watchdog. It is created by daemon.New and started by daemon.Run via Run(ctx).

func New

func New(dataDir, nodeIDHex string, auto, persistentService bool, networkReady func() bool, log *slog.Logger) *Updater

New creates an Updater. networkReady is called by the watchdog to confirm the new binary has established DHT connectivity. persistentService gates the automatic periodic check loop: when false, the loop is suppressed to avoid unrecoverable outages on manually-run daemons.

func (*Updater) Run

func (u *Updater) Run(ctx context.Context)

Run starts the update subsystem:

  • If update_state is "pending" for this binary, starts the health watchdog.
  • If auto is true, starts the periodic check loop after initialDelay.

Blocks until ctx is cancelled.

func (*Updater) Status

func (u *Updater) Status() map[string]any

Status returns fields for a2al_status / GET /update/status. Safe to call on a nil receiver (returns update_enabled:false).

func (*Updater) TriggerNow

func (u *Updater) TriggerNow(ctx context.Context) error

TriggerNow runs an immediate check and applies any available update, ignoring the rollout window. Used by POST /update/apply.

Jump to

Keyboard shortcuts

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