service

package
v0.1.22 Latest Latest
Warning

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

Go to latest
Published: Oct 26, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package service generates and manages an OS service definition (a launchd LaunchAgent on macOS, a systemd user unit on Linux) that keeps one Moltnet network's server running across reboots and restarts it on crash. It backs `moltnet service install|uninstall|start|stop|status` (PLAN.md phase 4, item 2).

Index

Constants

This section is empty.

Variables

View Source
var ErrNotInstalled = errors.New("moltnet service is not installed for this network")

ErrNotInstalled is returned by Start, Stop, Restart, and Uninstall when no unit/plist has been installed for the network yet.

Functions

func LaunchdLabel

func LaunchdLabel(networkID string) string

LaunchdLabel is the LaunchAgent label/filename stem used on darwin.

func LaunchdPlistPath

func LaunchdPlistPath(networkID string) (string, error)

LaunchdPlistPath returns ~/Library/LaunchAgents/dev.moltnet.<network-id>.plist.

func RenderLaunchdPlist

func RenderLaunchdPlist(spec Spec) (string, error)

RenderLaunchdPlist renders the LaunchAgent plist for spec. It is a pure function (no filesystem or launchctl access) so it can be golden-tested.

KeepAlive + RunAtLoad restart the server on crash and at login; stdout and stderr are redirected to fixed log files under spec.LogDir() so `moltnet service status` has somewhere to point operators at. Every path value is XML-escaped via plistString so an unusual (but valid) filesystem path never produces malformed XML.

func RenderSystemdUnit

func RenderSystemdUnit(spec Spec) (string, error)

RenderSystemdUnit renders the systemd user unit for spec. It is a pure function (no filesystem or systemctl access) so it can be golden-tested.

Restart=always plus a short RestartSec keeps the server running across crashes, mirroring the launchd KeepAlive behavior; stdout/stderr go to fixed log files under spec.LogDir() rather than only the journal, so `moltnet service status` can point at the same kind of path on both OSes.

func SystemdUnitName

func SystemdUnitName(networkID string) string

SystemdUnitName is the user unit file name used on linux.

func SystemdUnitPath

func SystemdUnitPath(networkID string) (string, error)

SystemdUnitPath returns ~/.config/systemd/user/moltnet-<network-id>.service.

Types

type ErrUnsupportedOS

type ErrUnsupportedOS struct {
	GOOS string
}

ErrUnsupportedOS is returned by lifecycle operations on any GOOS other than darwin and linux.

func (ErrUnsupportedOS) Error

func (e ErrUnsupportedOS) Error() string

type Manager

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

Manager installs, uninstalls, and controls the OS service for a Moltnet network. Use New for production code; NewForOS is the test seam that lets tests exercise the darwin and linux code paths regardless of the host they run on, without ever calling a real launchctl/systemctl.

func New

func New() *Manager

New returns a Manager that dispatches on the real runtime.GOOS and runs real launchctl/systemctl commands.

func NewForOS

func NewForOS(runner Runner, goos string) *Manager

NewForOS returns a Manager for goos ("darwin" or anything else, treated as linux-family for systemd), using runner instead of exec.Command. Tests use this to golden-test both platforms' lifecycle behavior from one host.

func (*Manager) Install

func (m *Manager) Install(ctx context.Context, spec Spec) error

Install renders and writes the platform unit file for spec, then loads (and, per KeepAlive/enable --now, starts) it. Re-running Install updates the file in place and reloads it, so editing a network's binary or config path just means re-running `moltnet service install`.

func (*Manager) InstalledNetworkIDs

func (m *Manager) InstalledNetworkIDs() ([]string, error)

InstalledNetworkIDs lists network ids with an installed unit/plist file for this Manager's GOOS: dev.moltnet.<id>.plist under ~/Library/LaunchAgents on darwin, moltnet-<id>.service under ~/.config/systemd/user on linux. `moltnet uninstall` unions this with the ~/.moltnet/<id>/ directory listing so a dangling service (its network directory already removed by hand) still gets stopped and unloaded.

func (*Manager) IsInstalled

func (m *Manager) IsInstalled(networkID string) (bool, error)

IsInstalled reports whether a unit/plist file exists for networkID, independent of the current GOOS's support: `pair --restart` uses this to give a clear "no managed service for this network" error rather than an OS-support error when the operator simply never ran `service install`.

func (*Manager) Restart

func (m *Manager) Restart(ctx context.Context, networkID string) error

Restart restarts the network's installed service, propagating ErrNotInstalled when it is not (the `pair --restart` error case).

func (*Manager) Start

func (m *Manager) Start(ctx context.Context, networkID string) error

Start starts (or restarts, if already running) the network's installed service.

func (*Manager) Status

func (m *Manager) Status(ctx context.Context, networkID string) (Status, error)

Status reports whether the network's service is installed and running.

func (*Manager) Stop

func (m *Manager) Stop(ctx context.Context, networkID string) error

Stop stops the network's installed service without uninstalling it.

func (*Manager) Uninstall

func (m *Manager) Uninstall(ctx context.Context, networkID string) error

Uninstall stops and unloads the network's service, then removes the unit file. It is not an error to uninstall a network that has no service installed; it is simply a no-op in that case.

func (*Manager) UnitPath

func (m *Manager) UnitPath(networkID string) (string, error)

UnitPath returns the platform-specific unit/plist file path for networkID: the plist under ~/Library/LaunchAgents on darwin, the unit file under ~/.config/systemd/user on linux. Callers (the CLI's `service` command) use this to tell the operator exactly what file was written.

type Runner

type Runner interface {
	Run(ctx context.Context, name string, args ...string) ([]byte, error)
}

Runner executes one external system command (launchctl or systemctl) and returns its combined output. Production code uses execRunner; tests inject a fake so they never touch the real service manager.

type Spec

type Spec struct {
	// NetworkID identifies the network and names the generated unit/label.
	NetworkID string
	// ConfigPath is the absolute path to the network's Moltnet config file,
	// passed to `moltnet start --config`.
	ConfigPath string
	// BinaryPath is the absolute path to the moltnet executable to run.
	BinaryPath string
	// NetworkDir is the absolute network home directory; stdout/stderr logs
	// are written under NetworkDir/.moltnet/.
	NetworkDir string
}

Spec describes the managed Moltnet server process for one network. All paths must be absolute: both launchd and systemd run units outside any particular working directory, so a relative path would resolve differently (or not at all) once the agent/unit is actually loaded.

func (Spec) LogDir

func (s Spec) LogDir() string

LogDir returns the directory service logs are written to: NetworkDir's .moltnet runtime-state directory, matching the convention used for relay.json and other per-network runtime files.

func (Spec) StderrLogPath

func (s Spec) StderrLogPath() string

func (Spec) StdoutLogPath

func (s Spec) StdoutLogPath() string

StdoutLogPath and StderrLogPath name the fixed log files launchd/systemd redirect the managed process's output to.

func (Spec) Validate

func (s Spec) Validate() error

Validate reports the first missing required field, so callers get one clear error instead of a generated unit referencing an empty path.

type Status

type Status struct {
	Installed bool
	Running   bool
	// Detail is the raw platform tool output (launchctl print / systemctl
	// status), included for operators debugging a stuck service.
	Detail string
}

Status is the result of `moltnet service status`.

Jump to

Keyboard shortcuts

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