idle

package
v0.0.199 Latest Latest
Warning

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

Go to latest
Published: Sep 15, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package idle decides exit-on-idle from snapshot stability + occupy probe.

Index

Constants

View Source
const (
	EventArmed    = "idle.armed"
	EventTick     = "idle.tick"
	EventReset    = "idle.reset"
	EventSoftExit = "idle.soft_exit"
	EventShutdown = "idle.shutdown"
)

Event names written to idle.jsonl.

View Source
const (
	ResetSnapshotErr = "snapshot_err"
	ResetChanged     = "changed"
	ResetNotReady    = "not_ready"
	ResetOccupied    = "occupied"
	ResetQueue       = "queue"
	ResetFinalOccupy = "final_occupy"
)

Reset reasons on idle.reset.

View Source
const DefaultGrace = 5 * time.Second

DefaultGrace is the post-SoftExit wait before Shutdown.

View Source
const DefaultSnapTailRunes = 200

DefaultSnapTailRunes is how many trailing runes to keep on soft_exit / reset=changed.

View Source
const FirstDelay = 30 * time.Second

FirstDelay is the earliest first snapshot when Timeout >= this. Timeouts shorter than this (e.g. 10s probes) sample immediately.

View Source
const SamplesPerCycle = 3

SamplesPerCycle is the max resting+occupy checks in one idle-exit cycle.

Variables

This section is empty.

Functions

func RunLoop

func RunLoop(ctx context.Context, w *Watchdog)

RunLoop sleeps on Schedule(Timeout) between Ticks until SoftExit+grace ForceShutdown, or ctx cancel. On idleHits==0 after a Tick, restarts the schedule from the first delay (start over).

func Schedule

func Schedule(timeout time.Duration) (first, gap time.Duration)

Schedule is the serve-loop sleep plan for one cycle: first delay, then two gaps. Timeouts < 30s start immediately (0, T/2, T). Longer timeouts wait 30s first (30s, 30s+(T-30s)/2, T). At most 3 snapshots.

func SleepCtx

func SleepCtx(ctx context.Context, d time.Duration) bool

SleepCtx sleeps d or returns false if ctx is done. d<=0 is a no-op success.

func SnapMeta added in v0.0.195

func SnapMeta(snap string) (hash string, length int)

SnapMeta returns sha256 hex (16 chars) and byte length for a resting snapshot.

func SnapTail added in v0.0.195

func SnapTail(snap string, n int) string

SnapTail returns the last n runes of snap (n<=0 → DefaultSnapTailRunes).

Types

type Event added in v0.0.195

type Event struct {
	TS         time.Time `json:"ts"`
	Event      string    `json:"event"`
	SessionID  string    `json:"session_id,omitempty"`
	Timeout    string    `json:"timeout,omitempty"`
	Grace      string    `json:"grace,omitempty"`
	Hits       int       `json:"hits,omitempty"`
	HitsBefore int       `json:"hits_before,omitempty"`
	IdleSince  string    `json:"idle_since,omitempty"`
	Age        string    `json:"age,omitempty"`
	Ready      *bool     `json:"ready,omitempty"`
	ReadyState string    `json:"ready_state,omitempty"`
	Occupy     string    `json:"occupy,omitempty"`
	Queue      *int      `json:"queue,omitempty"`
	Reason     string    `json:"reason,omitempty"`
	SnapHash   string    `json:"snap_hash,omitempty"`
	SnapLen    int       `json:"snap_len,omitempty"`
	SnapTail   string    `json:"snap_tail,omitempty"`
}

Event is one idle.jsonl line (compact JSON object).

type JSONL added in v0.0.195

type JSONL struct {
	Path string
	// contains filtered or unexported fields
}

JSONL appends Events as one JSON object per line. Safe for concurrent use.

func (*JSONL) Log added in v0.0.195

func (j *JSONL) Log(e Event)

Log appends e as a single JSON line. Creates the parent dir if needed. Failures are ignored (idle exit must not fail open because of logging).

type Policy

type Policy struct {
	ExitOnIdle  bool
	IdleTimeout time.Duration
}

Policy is the arming subset of idle-policy.json.

type Watchdog

type Watchdog struct {
	Timeout time.Duration
	Grace   time.Duration // 0 → DefaultGrace
	Now     func() time.Time

	// Snapshot returns the resting TTY snapshot text.
	Snapshot func() (string, error)
	// ProbeOccupied runs the space probe. When nil, Tick calls occupied.Probe
	// with the resting snap as Before + Snapshot + Inject.
	ProbeOccupied func() occupied.Status
	// Inject is used when ProbeOccupied is nil (no-submit " " / DEL).
	Inject func(text string) error
	// Ready is an optional hold (typically CheckWritable). nil → treat as ready.
	// Prevents SoftExit before the TUI can accept input / a draft.
	Ready func(snapshot string) bool
	// ReadyStatus when set is preferred over Ready and supplies ready_state for logs.
	ReadyStatus func(snapshot string) (ready bool, state string)
	// QueueLen is an optional hold. nil → treat as 0.
	QueueLen func() int

	SoftExit func()
	Shutdown func()

	// Log receives idle.jsonl events (armed/tick/reset/soft_exit/shutdown). nil → silent.
	Log func(Event)
	// SessionID is copied into log events when set.
	SessionID string
	// contains filtered or unexported fields
}

Watchdog is the injectable keep-alive idle-exit state machine.

Each Tick:

  1. capture resting snapshot (pre-space baseline for this tick)
  2. if changed vs last resting baseline → reset hits (start over)
  3. if not Ready (when set) → reset hits (do not probe yet)
  4. else probe occupy (space / compare / DEL), reusing resting snap as before
  5. keep resting baseline as the pre-space snap (DEL restores; do not Set(post-probe) — ephemeral placeholder collapse/restore must not look like session activity on the next Tick)
  6. if occupied → reset hits; Unknown after Ready is treated as empty
  7. if QueueLen > 0 → reset hits
  8. else count an idle hit; SoftExit after SamplesPerCycle consecutive hits and continuous idle ≥ Timeout

func New

func New(found bool, p Policy, cfg Watchdog) *Watchdog

New copies cfg. Tick is a no-op when !found or !p.ExitOnIdle. Timeout comes from p.IdleTimeout when cfg.Timeout == 0.

func (*Watchdog) ForceShutdown

func (w *Watchdog) ForceShutdown()

ForceShutdown fires Shutdown once (post-grace serve loop path).

func (*Watchdog) IdleHits

func (w *Watchdog) IdleHits() int

IdleHits is the consecutive idle-check count (0..SamplesPerCycle).

func (*Watchdog) LogArmed added in v0.0.195

func (w *Watchdog) LogArmed()

LogArmed writes idle.armed when the watchdog is armed and Log is set.

func (*Watchdog) SoftDone

func (w *Watchdog) SoftDone() bool

SoftDone reports whether SoftExit has already fired.

func (*Watchdog) Tick

func (w *Watchdog) Tick()

Tick advances one resting+occupy check.

Jump to

Keyboard shortcuts

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