notify

package
v0.12.2 Latest Latest
Warning

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

Go to latest
Published: Aug 18, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package notify implements a small persistent notification queue used by the projmux status bar. Entries are stored until explicit ack or the bounded reconcile policy evicts expired-gone or hard-cap overflow rows.

Note: the click handler in the status bar will call `projmux internal focus --target=... --source=os-notification` — but this package does NOT call focus itself. It is pure storage.

Index

Constants

View Source
const (
	SeverityInfo     = "info"
	SeverityWarn     = "warn"
	SeverityCritical = "critical"
)

Severity values accepted on push.

View Source
const (
	SourceAI       = "ai"
	SourceK8s      = "k8s"
	SourceGit      = "git"
	SourceExternal = "external"
)

Source values accepted on push.

View Source
const (
	MetaAgent    = "agent"
	MetaTopic    = "topic"
	MetaEvent    = "event"
	MetaCategory = "category"
	MetaState    = "state"
)

Metadata keys shared by the notify produce/consume/reconcile sites.

View Source
const DefaultTTL = 600 * time.Second

DefaultTTL is the default freshness window applied when the caller does not supply --ttl. Expiration alone does not remove a pending entry; reconcile requires both expiration and a gone target unless the hard cap is exceeded.

View Source
const MaxQueueEntries = 256

MaxQueueEntries is the hard upper bound applied by Reconcile. Push remains append/replace-only so producer and explicit-ack semantics do not change; the queue is trimmed to its most recent entries only during reconciliation.

View Source
const MaxTextLength = 80

MaxTextLength caps the stored Text on push. Longer text is truncated (preserving leading content). v0 keeps no extension field; the truncation is destructive.

View Source
const NotifyFileName = "notify.json"

NotifyFileName is the basename of the queue file inside StateDir.

Variables

View Source
var ErrInvalidSeverity = errors.New("invalid severity")

ErrInvalidSeverity indicates a severity value outside the allowed set.

View Source
var ErrInvalidSource = errors.New("invalid source")

ErrInvalidSource indicates a source value outside the allowed set.

View Source
var ErrInvalidTTL = errors.New("invalid ttl")

ErrInvalidTTL indicates a non-positive TTL was supplied.

View Source
var ErrInvalidTarget = errors.New("invalid target")

ErrInvalidTarget indicates the target string could not be parsed or the session field was empty.

View Source
var ErrInvalidText = errors.New("invalid text")

ErrInvalidText indicates the supplied text was empty after trimming.

View Source
var ErrNotFound = errors.New("notification not found")

ErrNotFound indicates an ack was requested for an unknown id.

Functions

func FormatTarget

func FormatTarget(t Target) string

FormatTarget renders a Target as SESSION[:WINDOW[.PANE]].

func ValidateSeverity

func ValidateSeverity(value string) error

ValidateSeverity returns nil if value is one of the accepted severities.

func ValidateSource

func ValidateSource(value string) error

ValidateSource returns nil if value is one of the accepted sources.

Types

type Clock

type Clock func() time.Time

Clock returns the current time. Tests inject a fixed clock.

type Notification

type Notification struct {
	ID        string            `json:"id"`
	Text      string            `json:"text"`
	Severity  string            `json:"severity"`
	Socket    string            `json:"socket,omitempty"`
	Session   string            `json:"session"`
	Window    string            `json:"window,omitempty"`
	Pane      string            `json:"pane,omitempty"`
	Source    string            `json:"source"`
	Metadata  map[string]string `json:"metadata,omitempty"`
	CreatedAt time.Time         `json:"created_at"`
	ExpiresAt time.Time         `json:"expires_at"`
}

Notification is a single queued status-bar entry.

type PushInput

type PushInput struct {
	ID       string
	Text     string
	Severity string
	Source   string
	Metadata map[string]string
	TTL      time.Duration
	Target   Target
}

PushInput captures the user-provided fields for a push call. CreatedAt is supplied by the store at write time so callers can leave it zero.

type PushResult

type PushResult struct {
	ID         string
	QueueLen   int
	Replaced   bool // true if the push replaced an entry with the same ID.
	WasExpired bool // true if the existing entry had already expired.
}

PushResult is returned to callers after a successful Push.

type ReconcileResult added in v0.8.0

type ReconcileResult struct {
	ExpiredGone int
	Overflow    int
	QueueLen    int
}

ReconcileResult summarizes automatic queue eviction.

func (ReconcileResult) Removed added in v0.8.0

func (r ReconcileResult) Removed() int

Removed returns the total number of entries evicted.

type Store

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

Store persists notifications to a JSON file inside StateDir.

func NewDefaultStore

func NewDefaultStore(paths config.Paths) *Store

NewDefaultStore builds a Store that uses the canonical notify.json under the supplied projmux paths.

func NewStore

func NewStore(path string) *Store

NewStore builds a Store rooted at the supplied path.

func (*Store) Ack

func (s *Store) Ack(id string) error

Ack removes a single entry by id and returns ErrNotFound if absent. Note that an entry whose ttl already expired still counts as "found" because users may ack a stale id without first listing.

func (*Store) AckAll

func (s *Store) AckAll() (int, error)

AckAll removes every entry from the queue.

func (*Store) List

func (s *Store) List() ([]Notification, error)

List returns all pending entries in recency-desc order. It is read-only: expiration metadata never causes List itself to remove an entry.

func (*Store) Path

func (s *Store) Path() string

Path returns the underlying queue file path.

func (*Store) Push

func (s *Store) Push(in PushInput) (Notification, PushResult, error)

Push appends or replaces a notification. Validation is performed first so invalid input does not contend for the lock.

func (*Store) Reconcile added in v0.8.0

func (s *Store) Reconcile(targetExists TargetExistsFunc) (ReconcileResult, error)

Reconcile applies the queue's bounded-retention policy atomically. It removes only expired entries whose tmux target no longer exists, then keeps at most MaxQueueEntries of the remaining entries, evicting oldest first. Live expired entries are retained unless they fall into the hard-cap overflow. This is the only automatic removal path; Push and List never evict.

func (*Store) SetClock

func (s *Store) SetClock(c Clock)

SetClock replaces the time source. Intended for tests.

type Target

type Target struct {
	Socket  string
	Session string
	Window  string
	Pane    string
}

Target groups the routing fields of a notification.

func ParseTarget

func ParseTarget(value string) (Target, error)

ParseTarget parses a SESSION[:WINDOW[.PANE]] string. The SESSION segment is required and must be non-empty after trimming.

type TargetExistsFunc added in v0.8.0

type TargetExistsFunc func(Notification) bool

TargetExistsFunc reports whether a notification's tmux target is still present. A nil function means target inventory is unavailable, so reconciliation skips TTL-based removal and only enforces the hard cap.

Jump to

Keyboard shortcuts

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