diff options
| author | Shulhan <ms@kilabit.info> | 2022-03-06 23:33:53 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2022-03-07 02:49:38 +0700 |
| commit | 707e43921181505f252f94fff53aada17dfd4f95 (patch) | |
| tree | a85ccbe7e72ee8c2bec608dd57699453355e0799 | |
| parent | 456bbd1166fd87984d98fbc6029b5ce9798e451b (diff) | |
| download | pakakeh.go-707e43921181505f252f94fff53aada17dfd4f95.tar.xz | |
lib/memfs: add method Watch to MemFS
The Watch method create and start a DirWatcher that ready to be consumed.
This is to simplify watching an existing MemFS instance because the
internal fs inside the DirWatcher is not exported.
| -rw-r--r-- | lib/memfs/memfs.go | 42 | ||||
| -rw-r--r-- | lib/memfs/memfs_example_test.go | 71 |
2 files changed, 108 insertions, 5 deletions
diff --git a/lib/memfs/memfs.go b/lib/memfs/memfs.go index 79caae1d..a1cfa331 100644 --- a/lib/memfs/memfs.go +++ b/lib/memfs/memfs.go @@ -35,8 +35,10 @@ type MemFS struct { PathNodes *PathNode Root *Node Opts *Options - incRE []*regexp.Regexp - excRE []*regexp.Regexp + dw *DirWatcher + + incRE []*regexp.Regexp + excRE []*regexp.Regexp } // @@ -316,9 +318,11 @@ func (mfs *MemFS) Open(path string) (http.File, error) { // If child is not part if node's childrens it will return nil. // func (mfs *MemFS) RemoveChild(parent *Node, child *Node) (removed *Node) { - removed = parent.removeChild(child) - if removed != nil { - mfs.PathNodes.Delete(removed.Path) + if parent != nil { + removed = parent.removeChild(child) + if removed != nil { + mfs.PathNodes.Delete(removed.Path) + } } return } @@ -402,6 +406,34 @@ func (mfs *MemFS) Update(node *Node, newInfo os.FileInfo) { } } +// +// Watch create and start the DirWatcher that monitor the memfs Root +// directory. +// The MemFS will update the tree and node content automatically if the file +// get deleted or updated. +// The returned channel nsq is ready to be consumed. +// +func (mfs *MemFS) Watch(d time.Duration) (dw *DirWatcher, err error) { + var ( + logp = "Watch" + ) + + dw = &DirWatcher{ + fs: mfs, + Delay: d, + Options: *mfs.Opts, + } + + err = dw.Start() + if err != nil { + // There should be no error here, since we already check and + // filled the required fields for DirWatcher. + return nil, fmt.Errorf("%s: %w", logp, err) + } + + return dw, nil +} + func (mfs *MemFS) createRoot() error { logp := "createRoot" diff --git a/lib/memfs/memfs_example_test.go b/lib/memfs/memfs_example_test.go index 250d7949..25f257e2 100644 --- a/lib/memfs/memfs_example_test.go +++ b/lib/memfs/memfs_example_test.go @@ -2,7 +2,11 @@ package memfs import ( "fmt" + "io/ioutil" "log" + "os" + "path/filepath" + "time" ) func ExampleNew() { @@ -87,3 +91,70 @@ func ExampleMemFS_Search() { // Path: /index.css // Snippets: ["body {\n}\n"] } + +func ExampleMemFS_Watch() { + var ( + mfs *MemFS + dw *DirWatcher + node *Node + opts Options + ns NodeState + err error + ) + + opts.Root, err = ioutil.TempDir("", "memfs_watch") + if err != nil { + log.Fatal(err) + } + + defer func() { + _ = os.RemoveAll(opts.Root) + }() + + mfs, err = New(&opts) + if err != nil { + log.Fatal(err) + } + + dw, err = mfs.Watch(200 * time.Millisecond) + if err != nil { + log.Fatal(err) + } + + // Wait for the goroutine on Watch run. + time.Sleep(200 * time.Millisecond) + + testFile := filepath.Join(opts.Root, "file") + err = os.WriteFile(testFile, []byte("dummy content"), 0700) + if err != nil { + log.Fatal(err) + } + + ns = <-dw.C + fmt.Printf("State: %s\n", ns.State) + + node, err = mfs.Get("/file") + if err != nil { + log.Fatal(err) + } + fmt.Printf("Node: %s: %q\n", node.Path, node.Content) + + err = os.Remove(testFile) + if err != nil { + log.Fatal(err) + } + + ns = <-dw.C + fmt.Printf("State: %s\n", ns.State) + + node, _ = mfs.Get("/file") + fmt.Printf("Node: %s: %v\n", ns.Node.Path, node) + + dw.Stop() + + //Output: + //State: FileStateCreated + //Node: /file: "dummy content" + //State: FileStateDeleted + //Node: /file: <nil> +} |
