watcher

package
v2.6.0-beta1 Latest Latest
Warning

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

Go to latest
Published: Jun 13, 2026 License: MPL-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package watcher provides recursive filesystem watching with debouncing for blog post directories.

It wraps github.com/fsnotify/fsnotify with automatic recursive directory watching (fsnotify only watches individual directories non-recursively) and a configurable debounce window that coalesces rapid bursts of events — such as those produced by editors that write files in multiple steps — into a single callback invocation.

Basic Usage

Create a Watcher rooted at a posts directory and run it alongside a pkg/server.Server to achieve live content reload:

import (
    "context"
    "log/slog"
    "os"

    "github.com/harrydayexe/GoBlog/v2/pkg/config"
    "github.com/harrydayexe/GoBlog/v2/pkg/server"
    "github.com/harrydayexe/GoBlog/v2/pkg/watcher"
)

postsPath := "posts/"
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))

w, err := watcher.New(postsPath, config.WithLogger(logger).AsWatcherOption())
if err != nil {
    log.Fatal(err)
}

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

// srv is a *server.Server created with server.New(...)
go w.Run(ctx, func(ctx context.Context) {
    if err := srv.UpdatePosts(os.DirFS(postsPath), ctx); err != nil {
        slog.Warn("failed to reload posts", "error", err)
    }
})

// srv.Run blocks until the server shuts down.
if err := srv.Run(ctx); err != nil {
    log.Fatal(err)
}

Setup Errors

New fails hard on any problem detected at setup time: root path missing or not a directory, fsnotify initialisation failure, or any individual directory failing to be added to the watch list (e.g. due to exceeding the Linux inotify watch limit). These are surfaced immediately so the user is aware that watching is not working as requested.

Runtime Behaviour

Once Run is active, errors are logged at warn level and the loop continues. This includes fsnotify errors and failures adding newly created subdirectories to the watch set.

Subdirectories created after the Watcher is constructed are automatically picked up by Run when the parent directory fires a Create event.

Only changes to files with a .md extension trigger the onChange callback. All other file types (images, CSS, YAML, etc.) are silently ignored, as are common editor temporary files (dotfiles, *.swp, *~, etc.). Deletion of watched subdirectories releases the corresponding watch descriptor automatically. A subdirectory that is removed and then recreated is re-watched when the parent fires the subsequent Create event.

Concurrency

New and Run are not safe for concurrent use on the same Watcher. Typically a single Watcher is created once and Run in a dedicated goroutine.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Watcher

type Watcher struct {
	config.WatcherDebounce
	config.Logger
	// contains filtered or unexported fields
}

Watcher watches a directory tree for filesystem changes and invokes a callback, debounced, whenever changes are detected.

func New

func New(path string, opts ...config.WatcherOption) (*Watcher, error)

New creates a Watcher rooted at path. It recursively watches path and all subdirectories that exist at creation time. Subdirectories created after New returns are picked up automatically inside Run when their parent fires a Create event.

New fails immediately if any part of setup fails — including the root path being missing, fsnotify initialisation failing, or any subdirectory failing to be added to the watch list. Callers should not attempt to fall back silently; surface the error to the user.

Call Run to begin receiving events.

func (*Watcher) Run

func (w *Watcher) Run(ctx context.Context, onChange func(context.Context)) error

Run blocks, watching for filesystem events, until ctx is canceled. onChange is invoked (with a child context) whenever file changes are detected, coalesced over the configured debounce window. Multiple events within the window trigger only one onChange call.

Errors from the fsnotify event stream are logged at warn level but do not stop the watch loop. Run returns nil when ctx is canceled.

Jump to

Keyboard shortcuts

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