Documentation
¶
Overview ¶
Package idle decides exit-on-idle from snapshot stability + occupy probe.
Index ¶
- Constants
- func RunLoop(ctx context.Context, w *Watchdog)
- func Schedule(timeout time.Duration) (first, gap time.Duration)
- func SleepCtx(ctx context.Context, d time.Duration) bool
- func SnapMeta(snap string) (hash string, length int)
- func SnapTail(snap string, n int) string
- type Event
- type JSONL
- type Policy
- type Watchdog
Constants ¶
const ( EventArmed = "idle.armed" EventTick = "idle.tick" EventReset = "idle.reset" EventSoftExit = "idle.soft_exit" EventShutdown = "idle.shutdown" )
Event names written to idle.jsonl.
const ( ResetSnapshotErr = "snapshot_err" ResetChanged = "changed" ResetNotReady = "not_ready" ResetOccupied = "occupied" ResetQueue = "queue" ResetFinalOccupy = "final_occupy" )
Reset reasons on idle.reset.
const DefaultGrace = 5 * time.Second
DefaultGrace is the post-SoftExit wait before Shutdown.
const DefaultSnapTailRunes = 200
DefaultSnapTailRunes is how many trailing runes to keep on soft_exit / reset=changed.
const FirstDelay = 30 * time.Second
FirstDelay is the earliest first snapshot when Timeout >= this. Timeouts shorter than this (e.g. 10s probes) sample immediately.
const SamplesPerCycle = 3
SamplesPerCycle is the max resting+occupy checks in one idle-exit cycle.
Variables ¶
This section is empty.
Functions ¶
func RunLoop ¶
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 ¶
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.
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.
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:
- capture resting snapshot (pre-space baseline for this tick)
- if changed vs last resting baseline → reset hits (start over)
- if not Ready (when set) → reset hits (do not probe yet)
- else probe occupy (space / compare / DEL), reusing resting snap as before
- 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)
- if occupied → reset hits; Unknown after Ready is treated as empty
- if QueueLen > 0 → reset hits
- else count an idle hit; SoftExit after SamplesPerCycle consecutive hits and continuous idle ≥ Timeout
func New ¶
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) LogArmed ¶ added in v0.0.195
func (w *Watchdog) LogArmed()
LogArmed writes idle.armed when the watchdog is armed and Log is set.