-
Notifications
You must be signed in to change notification settings - Fork 242
Proposed API Changes #64
Description
I'm currently working on an internal event processing pipeline that will replace purgeEvents(), calling a series of functions to handle recursive watches (#56), throttling (#62), along with basic filtering and logging. I would prefer to keep the pipeline itself internal, at least initially, but there are still some API changes.
- improve testability
- surface new options
- aesthetics
fsnotify.Event interface
In order to unit test pipeline steps, I would like to fake the event being passed in, which can be accomplished with an interface:
type Event interface {
IsCreate() bool
IsDelete() bool
IsModify() bool
IsRename() bool
Path() string
}As an interface cannot contain a field, the pipeline expects a Path() method, rather than a Name field.
The Watcher API still provides a concrete Event chan *FileEvent that contains a Name field in addition to Path(). Even so, I think it would be good to export the Event interface and to mark the Name field as deprecated.
New Options
These options don't necessarily correspond one-to-one with the steps in the pipeline, but they do represent the configuration those steps need.
type Options struct {
Recursive bool
Hidden bool
Pattern string
Throttle bool
ThrottleDuration time.Duration
Triggers Triggers
Verbose bool
}In order to specify these options, a new WatchPath method is introduced. The options have reasonable defaults, mostly using zero-initialization, though ThrottleDuration and Triggers don't have zero value defaults.
err = watcher.WatchPath("./", &fsnotify.Options{
Recursive: true,
WatchHidden: false,
Pattern: "*.go,*.c",
Triggers: fsnotify.Create | fsnotify.Modify,
Throttle: true,
ThrottleDuration: 1 * time.Second, // default
Verbose: true,
})Watch & WatchFlags work as before, but are marked as deprecated. Of note, they continue to watch hidden files/directories (WatchHidden: true).
It may be more appropriate if some of these options were specified at a "global" level rather than per-Watch, but I would rather not change the NewWatcher() API. I suppose we could add some accessors to the Watcher instead?
A number of options don't really make sense when watching a single file. I wonder if anyone is using fsnotify for that purpose, and whether or not FSEvents (#54) supports single file watches. If so, I'm sure we can come up with a solution beyond "don't use these options in this case", perhaps a WatchFile() method?
Triggers type
When looking through the Go standard library, I've seen constants in ALL_CAPS and TitleCase. I'm not aware of an official reason to choose one over the other, but I find the following looks a little nicer on a page than FSN_CREATE, etc.
type Triggers uint32
const (
Create Triggers = 1 << iota
Modify
Delete
Rename
allEvents Triggers = Modify | Delete | Rename | Create // default
)Outside of introducing a type for the constants, this is mostly an aesthetic change. The internal representation is exactly the same.
Comments
While working away on a first pull request, I would appreciate any early feedback on the naming and approach described here. Thanks!