daemon

package
v0.0.6 Latest Latest
Warning

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

Go to latest
Published: Oct 16, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package daemon manages the cloop background daemon process. It stores PID in .cloop/daemon.pid, state in .cloop/daemon.json, and log output in .cloop/daemon.log.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsRunning

func IsRunning(workdir string) (bool, int)

IsRunning returns true if the daemon is alive (PID file exists and process responds).

func LogPath

func LogPath(workdir string) string

LogPath returns the absolute path to the daemon log file.

func PIDPath

func PIDPath(workdir string) string

PIDPath returns the absolute path to the PID file.

func ReadPID

func ReadPID(workdir string) int

ReadPID reads the daemon PID from .cloop/daemon.pid; returns 0 if not found.

func RemovePID

func RemovePID(workdir string) error

RemovePID removes the PID file (called by worker on clean exit). Returns the underlying os.Remove error so callers can log a true failure (perms, busy filesystem) — a stale PID file blocks the next `daemon start` because IsRunning() will see it and assume the prior worker is alive. ENOENT is expected when the file was already removed (e.g. by Stop) and is returned untouched so callers can filter with os.IsNotExist.

func StatePath

func StatePath(workdir string) string

StatePath returns the absolute path to the daemon state file.

func Stop

func Stop(workdir string) error

Stop sends SIGTERM to the daemon worker and waits for it to exit, escalating to SIGKILL if the worker doesn't terminate within stopGraceTimeout.

Unlike a fire-and-forget signal + os.Remove(pidPath), this:

  1. Lets the worker run its own cleanup (PID-file removal, final state Save, HTTP-server graceful shutdown) before Stop returns. A subsequent `daemon start` therefore sees a clean slate instead of racing the drain.
  2. Forcibly cleans up if the worker is wedged, so a stuck daemon can always be replaced.

Returns nil on clean exit; a wrapped error if SIGKILL was needed (the daemon is gone, but the caller should know it didn't shut down cleanly).

func StopWithTimeout

func StopWithTimeout(workdir string, grace time.Duration) error

StopWithTimeout is Stop with a caller-supplied grace period. Used by tests to drive the SIGKILL escalation path without waiting the production default.

func WritePID

func WritePID(workdir string, pid int) error

WritePID writes the daemon PID to .cloop/daemon.pid atomically.

Types

type State

type State struct {
	PID                 int       `json:"pid"`
	StartedAt           time.Time `json:"started_at"`
	LastRunAt           time.Time `json:"last_run_at,omitempty"`
	NextRunAt           time.Time `json:"next_run_at,omitempty"`
	RunCount            int       `json:"run_count"`
	TotalTasksCompleted int       `json:"total_tasks_completed"`
	TotalTasksFailed    int       `json:"total_tasks_failed"`
	Status              string    `json:"status"` // starting, idle, running, stopped, error
	Interval            string    `json:"interval"`
	Provider            string    `json:"provider,omitempty"`
	Model               string    `json:"model,omitempty"`
	LastError           string    `json:"last_error,omitempty"`
	WatchEnabled        bool      `json:"watch_enabled,omitempty"`
	WatchTriggers       int       `json:"watch_triggers,omitempty"`
}

State tracks the daemon's runtime status, persisted to .cloop/daemon.json.

func Load

func Load(workdir string) (*State, error)

Load reads the daemon state from disk; returns nil if not found.

On parse failure (zero-byte file, schema drift, manual edit gone wrong) the corrupt file is quarantined aside as daemon.json.corrupt-<unix> and (nil, nil) is returned. Losing the daemon counters/last-error is preferable to wedging `cloop daemon status` and the orchestrator's heartbeat reads — the bytes are preserved next to the original location for forensics.

func (*State) Save

func (s *State) Save(workdir string) error

Save writes the daemon state to disk atomically. The write is serialized per-workdir so concurrent Save calls from the daemon worker's goroutines never produce a torn or partially-written .cloop/daemon.json file.

Jump to

Keyboard shortcuts

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