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 ¶
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 ¶
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.
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 ¶
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.
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.