daemon

package
v0.16.0 Latest Latest
Warning

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

Go to latest
Published: May 6, 2026 License: Apache-2.0 Imports: 19 Imported by: 0

Documentation

Overview

Package daemon implements a long-running consumer that pulls AILANG cloud events from Pub/Sub subscriptions and surfaces them as native macOS notifications. Designed to run under launchd.

Index

Constants

This section is empty.

Variables

View Source
var EnvProject = map[string]struct {
	Project string
	Prefix  string
}{
	"dev":  {Project: "ailang-multivac-dev", Prefix: "ailang-dev"},
	"test": {Project: "ailang-multivac-test", Prefix: "ailang-test"},
	"prod": {Project: "ailang-multivac", Prefix: "ailang"},
}

EnvProject maps the --env flag to a (GCP project, prefix) tuple. Mirrors the per-environment terraform tfvars in ailang-multivac.

Functions

func Install

func Install(opts InstallOpts) error

Install renders and loads the launchd plist for the daemon. Returns an error if a plist already exists and Force is false.

func LoadExcludes

func LoadExcludes(path string) ([]string, error)

LoadExcludes reads one substring per non-blank, non-`#`-prefixed line. Path defaults to ~/.ailang/config/notify_excludes.conf. Missing file is not an error — returns nil slice.

func Status

func Status() (string, error)

Status returns a one-line human-readable summary of the daemon's launchd state. Does not return error for "not installed" — that's reported in the returned string.

func Uninstall

func Uninstall() error

Uninstall unloads the daemon (if loaded) and removes the plist. Missing plist is treated as a no-op.

Types

type Config

type Config struct {
	EventsSub   string        // e.g. "events-laptop"
	MessagesSub string        // e.g. "messages-laptop"
	TaskWindow  time.Duration // dedup window for task events
	MsgWindow   time.Duration // dedup window for message events
	Excludes    []string      // substring matches against title/body
	DryRun      bool          // skip the notifier; log instead
	Logger      *log.Logger   // optional; defaults to log.Default()
}

Config holds runtime parameters for the daemon. Marshalled from ~/.ailang/config/daemon.yaml in production; constructed directly in tests.

func ConfigForEnv

func ConfigForEnv(env string, fc FileConfig) (Config, string, string, error)

ConfigForEnv builds a daemon Config from a --env value, applying file-config overrides where present. Returns the resolved (project, prefix) for the caller to plumb into the Pub/Sub client. Returns an error if env is unknown.

type Daemon

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

Daemon is the running pull loop.

func New

func New(cfg Config, sub EventSubscriber, fetcher MessageFetcher, notifyFn func(notify.Notification) error) *Daemon

New constructs a Daemon. Pass interface implementations for sub/fetcher so tests can substitute fakes.

func (*Daemon) Run

func (d *Daemon) Run(ctx context.Context) error

Run blocks until ctx is cancelled, pulling from both subscriptions in parallel and firing notifications for relevant events. Returns nil on a clean shutdown; returns the first error from a subscription if one fails.

type EventSubscriber

type EventSubscriber interface {
	Subscribe(ctx context.Context, subName string, handler MessageHandler) error
}

EventSubscriber is the minimum surface the daemon needs from Pub/Sub. Production wiring uses an adapter around *pubsub.Subscriber; tests substitute an in-memory fake.

type FileConfig

type FileConfig struct {
	Env           string `yaml:"env"`             // dev|test|prod (default: prod)
	Inbox         string `yaml:"inbox"`           // user inbox name (default: empty = surface all)
	TaskWindowSec int    `yaml:"task_window_sec"` // dedup window for task events (default: 60)
	MsgWindowSec  int    `yaml:"msg_window_sec"`  // dedup window for messages   (default: 300)
	DryRun        bool   `yaml:"dry_run"`         // skip notifier (default: false)
	ExcludesPath  string `yaml:"excludes_path"`   // override path to notify_excludes.conf
}

FileConfig is the on-disk shape of ~/.ailang/config/daemon.yaml. Optional; every field has a sensible default.

func LoadFileConfig

func LoadFileConfig() (FileConfig, error)

LoadFileConfig reads ~/.ailang/config/daemon.yaml if present. Returns a zero-value FileConfig with no error if the file does not exist.

type InstallOpts

type InstallOpts struct {
	Env        string // dev|test|prod
	BinaryPath string // absolute path to the ailang binary
	Force      bool   // overwrite existing plist
}

InstallOpts controls plist generation.

type MessageFetcher

type MessageFetcher interface {
	Fetch(ctx context.Context, messageID string) (*messaging.InboxMessage, error)
}

MessageFetcher resolves a Pub/Sub MessageNotification (which carries only a MessageID) to the full InboxMessage. Production wiring reads Firestore via messaging.Store; tests substitute an in-memory fake.

type MessageHandler

type MessageHandler func(ctx context.Context, data []byte, attrs map[string]string) error

MessageHandler matches internal/pubsub.MessageHandler — exposed here so the daemon can unit-test against a fake Pub/Sub subscriber without depending on the gpubsub package.

Jump to

Keyboard shortcuts

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