Documentation
¶
Overview ¶
Package watch is the t06 iter-log filesystem watcher → SSE-broker bridge (plan task t06-recompute-on-miss-and-fswatch): the v1 standalone push path that exists BEFORE R3's publish primitive lands.
It watches the configured iter-log roots for iteration-log and score-sidecar changes and publishes the API.md §3.7 dashboard events to the t04 broker's Publisher seam. Every payload implements events.IterLogRooter (carrying the root in an unexported, non-marshaled field, since the event schema pins the payload key set) so the broker's per-root cache eviction fires instead of the coarser whole-cache fallback.
Watch semantics resolve spec OQ3 as the plan pinned it: fsnotify is the primary source AND a 1-second mtime poll runs alongside it as a belt-and-suspenders fallback — whichever fires first wins. Both paths feed one per-file (path, mtime) dedupe table, so a change reported by fsnotify is not re-published by the next poll tick and vice versa.
When R3's publisher lands (t13) this watcher demotes to fallback only: R3's in-process publish becomes the primary path, and the watcher remains for writers that do not go through R3 (e.g. a developer running `da score run` manually).
Index ¶
Constants ¶
const DefaultPollInterval = time.Second
DefaultPollInterval is the OQ3 mtime-poll fallback cadence: 1 second, so the poll alone still lands a push well inside the spec's 2-second budget even when FSEvents latency eats the fsnotify margin.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type IterationScored ¶
type IterationScored struct {
SessionID string `json:"session_id"`
Iteration int `json:"iteration"`
Band string `json:"band,omitempty"`
// contains filtered or unexported fields
}
IterationScored is the iteration.scored / score.recomputed payload (dashboard-event schema: session_id + iteration + optional band). It reports its iter-log root via IterLogRoot for per-root cache eviction without leaking the root into the marshaled payload.
func (IterationScored) IterLogRoot ¶
func (p IterationScored) IterLogRoot() string
IterLogRoot implements events.IterLogRooter.
type Option ¶
type Option func(*Watcher)
Option configures a Watcher.
func WithLogger ¶
WithLogger sets the structured logger used for skipped-file and watch warnings.
func WithPollInterval ¶
WithPollInterval overrides the OQ3 poll-fallback cadence. Zero keeps DefaultPollInterval; negative disables the poll (fsnotify-only — tests and callers that want deterministic single-source behavior).
type SessionUpdated ¶
type SessionUpdated struct {
SessionID string `json:"session_id"`
// contains filtered or unexported fields
}
SessionUpdated is the session.updated payload (dashboard-event schema: session_id only), likewise root-scoped for per-root eviction.
func (SessionUpdated) IterLogRoot ¶
func (p SessionUpdated) IterLogRoot() string
IterLogRoot implements events.IterLogRooter.
type Watcher ¶
type Watcher struct {
// contains filtered or unexported fields
}
Watcher bridges filesystem changes under the iter-log roots to broker events. Construct with New, start with Start, stop with Close. Safe for the concurrent fsnotify + poll sources it runs internally.
func New ¶
New builds a Watcher over the given iter-log roots, publishing to pub (the t04 broker's Publisher seam).
func (*Watcher) Close ¶
func (w *Watcher) Close()
Close stops both sources and waits for their goroutines. Idempotent.
func (*Watcher) Start ¶
Start seeds the baseline (pre-existing files publish nothing), registers the fsnotify watches, and launches the fsnotify and poll sources. An inactive fsnotify source — the constructor erroring OR every root failing to register — degrades to poll-only with a warning; it is an error only when the poll fallback is disabled too, because a watcher with zero active sources is dead and must not report healthy.