watch

package
v0.4.1 Latest Latest
Warning

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

Go to latest
Published: Sep 6, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package watch provides file-system watching with debounced sync callbacks. Ported from src/sync/watcher.ts and src/sync/watch-policy.ts of github.com/colbymchenry/codegraph (MIT).

Index

Constants

View Source
const DefaultDebounceMS = 2000

DefaultDebounceMS is the default debounce delay before a sync is triggered after the last file-change event (2000 ms, matching the original).

View Source
const DefaultMaxDirWatches = 50_000

DefaultMaxDirWatches caps the number of simultaneously-watched directories on Linux (per-directory inotify path). Matches the original's 50 000.

Variables

This section is empty.

Functions

func DetectWSL

func DetectWSL() bool

DetectWSL reports whether the current process is running under WSL. The result is cached after the first call.

func EmitEventForTests

func EmitEventForTests(root, relPath string) bool

EmitEventForTests feeds a synthetic event to the live watcher registered for root. Returns false if no watcher is registered. For use in tests only.

func IsLockUnavailableError

func IsLockUnavailableError(err error) bool

IsLockUnavailableError reports whether err is (or wraps) a LockUnavailableError.

func ResetWSLCacheForTests

func ResetWSLCacheForTests()

ResetWSLCacheForTests resets the cached WSL detection so tests can control the outcome deterministically. Never call outside tests.

func WatchDisabledReason

func WatchDisabledReason(projectRoot string, probe WatchProbe) string

WatchDisabledReason returns a human-readable reason why file watching should be skipped for projectRoot, or "" when watching should proceed.

Precedence (first match wins):

  1. CODEGRAPH_NO_WATCH=1 → off (explicit opt-out always wins)
  2. CODEGRAPH_FORCE_WATCH=1 → on (overrides auto-detection)
  3. WSL2 + /mnt/* drive → off (recursive fs.watch is too slow; #199)

Types

type FileWatcher

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

FileWatcher watches a project root for source-file changes and calls a debounced sync callback.

func New

func New(root string, syncFn SyncFunc, opts Options) *FileWatcher

New creates a FileWatcher that has not yet started. Call FileWatcher.Start to begin watching.

func (*FileWatcher) IngestEventForTests

func (fw *FileWatcher) IngestEventForTests(relPath string)

IngestEventForTests feeds a synthetic project-relative path through the full filter → pendingFiles → debounce pipeline. Only for use in tests.

func (*FileWatcher) IsActive

func (fw *FileWatcher) IsActive() bool

IsActive reports whether the watcher is currently running.

func (*FileWatcher) PendingFiles

func (fw *FileWatcher) PendingFiles() []PendingFile

PendingFiles returns a snapshot of files seen since the last successful sync.

func (*FileWatcher) Start

func (fw *FileWatcher) Start() bool

Start begins watching. Returns true if watching started, false if disabled (e.g., CODEGRAPH_NO_WATCH or WSL2 /mnt drive).

func (*FileWatcher) Stop

func (fw *FileWatcher) Stop()

Stop shuts down the watcher and clears state.

func (*FileWatcher) WaitUntilReady

func (fw *FileWatcher) WaitUntilReady(timeout time.Duration) error

WaitUntilReady blocks until the watch set is established, or until the context deadline is reached.

type IsIgnoredFunc

type IsIgnoredFunc func(relPath string) bool

IsIgnoredFunc reports whether a project-relative POSIX path should be ignored entirely (not just non-source, but also not a directory to recurse into on Linux).

type IsSourceFileFunc

type IsSourceFileFunc func(relPath string) bool

IsSourceFileFunc reports whether a project-relative POSIX path is a source file that should be indexed.

type LockUnavailableError

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

ErrLockUnavailable signals that the sync callback could not acquire the cross-process write lock. The watcher keeps pendingFiles intact and reschedules rather than reporting this as an error. Matches the original's LockUnavailableError.

func NewLockUnavailableError

func NewLockUnavailableError(msg string) *LockUnavailableError

NewLockUnavailableError wraps a message as a LockUnavailableError.

func (*LockUnavailableError) Error

func (e *LockUnavailableError) Error() string

type NowFunc

type NowFunc func() time.Time

NowFunc returns the current wall-clock time. Injectable for tests.

type Options

type Options struct {
	// DebounceMs is the debounce delay in ms. 0 uses DefaultDebounceMS.
	// Override via CODEGRAPH_WATCH_DEBOUNCE_MS env var (read at construction).
	DebounceMs int

	// OnSyncComplete is called after each successful sync.
	OnSyncComplete func(SyncResult)

	// OnSyncError is called when syncFn returns an error that is NOT
	// ErrLockUnavailable.
	OnSyncError func(error)

	// IsSourceFile decides whether a project-relative path should be tracked.
	// Defaults to a built-in set of Go/TS/JS extensions.
	IsSourceFile IsSourceFileFunc

	// IsIgnored decides whether a project-relative path should be dropped
	// entirely (before the IsSourceFile check). Defaults to nil (nothing extra
	// ignored beyond .codegraph/ and .git/).
	IsIgnored IsIgnoredFunc

	// Now overrides the clock. Defaults to time.Now.
	Now NowFunc

	// MaxDirWatches caps the Linux per-directory watch count. 0 = DefaultMaxDirWatches.
	MaxDirWatches int

	// InertForTests disables all OS-level watchers. Events are only fed
	// through [FileWatcher.IngestEventForTests].
	InertForTests bool
}

Options configures a FileWatcher.

type PendingFile

type PendingFile struct {
	// Path is the project-relative POSIX path (e.g. "src/foo.ts").
	Path string
	// FirstSeenMs is the wall-clock ms at the first event since the last sync.
	FirstSeenMs int64
	// LastSeenMs is the wall-clock ms at the most-recent event.
	LastSeenMs int64
	// Indexing is true when a sync is in flight that started after this
	// file's most-recent event — meaning the next successful sync will
	// absorb the edit.
	Indexing bool
}

PendingFile is a source file the watcher observed since the last successful sync. Exposed via FileWatcher.PendingFiles so callers can flag stale results without blocking on a sync.

type SyncFunc

type SyncFunc func() (SyncResult, error)

SyncFunc is the callback the watcher invokes after each debounce window. It should return ErrLockUnavailable when the cross-process write lock is held; the watcher retries without clearing pendingFiles in that case.

type SyncResult

type SyncResult struct {
	FilesChanged int
	DurationMs   int
}

SyncResult is the value returned by a successful sync callback.

type WatchProbe

type WatchProbe struct {
	// Env overrides os.Environ lookups. nil means use os.Getenv.
	Env map[string]string
	// IsWSL overrides the WSL detection when non-nil.
	IsWSL *bool
}

WatchProbe holds injectable inputs for WatchDisabledReason so tests can control the decision without touching real env vars or /proc/version.

Jump to

Keyboard shortcuts

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