mirror of
https://github.com/Theodor-Springmann-Stiftung/kgpz_web.git
synced 2025-10-29 09:05:30 +00:00
Better Watcher; butt it restarts 1000 times on one file change
This commit is contained in:
@@ -1,38 +1,93 @@
|
|||||||
package helpers
|
package helpers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"io/fs"
|
||||||
"log"
|
"log"
|
||||||
|
"path/filepath"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/fsnotify/fsnotify"
|
"github.com/fsnotify/fsnotify"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var NotInitializedError = errors.New("FileWatcher not initialized")
|
||||||
|
var NoWatchFunctionError = errors.New("No watch function provided")
|
||||||
|
|
||||||
type IFileWatcher interface {
|
type IFileWatcher interface {
|
||||||
GetEvents() chan string
|
RecursiveDir(path string) error
|
||||||
|
Dir(path string) error
|
||||||
|
Append(fn func(string))
|
||||||
|
Prepend(fn func(string))
|
||||||
|
Watch() error
|
||||||
|
Close()
|
||||||
|
Restart()
|
||||||
}
|
}
|
||||||
|
|
||||||
type FileWatcher struct {
|
type FileWatcher struct {
|
||||||
path []string
|
mu sync.Mutex
|
||||||
events chan string
|
wf []func(string)
|
||||||
|
paths []string
|
||||||
watcher *fsnotify.Watcher
|
watcher *fsnotify.Watcher
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFileWatcher(path []string) (*FileWatcher, error) {
|
func NewFileWatcher() (*FileWatcher, error) {
|
||||||
fw := &FileWatcher{path: path, events: make(chan string, 48)}
|
|
||||||
err := fw.Watch(path)
|
fw := &FileWatcher{mu: sync.Mutex{}}
|
||||||
if err != nil {
|
fw.Watch()
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return fw, nil
|
return fw, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fw *FileWatcher) Watch(paths []string) error {
|
func (fw *FileWatcher) RecursiveDir(path string) error {
|
||||||
fw.events = make(chan string, 48)
|
err := filepath.WalkDir(path, func(path string, d fs.DirEntry, err error) error {
|
||||||
|
if d.IsDir() {
|
||||||
|
err := fw.Dir(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fw *FileWatcher) Dir(path string) error {
|
||||||
|
fw.mu.Lock()
|
||||||
|
defer fw.mu.Unlock()
|
||||||
|
if fw.watcher != nil {
|
||||||
|
err := fw.watcher.Add(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fw.paths = append(fw.paths, path)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fw *FileWatcher) Append(fn func(string)) {
|
||||||
|
fw.mu.Lock()
|
||||||
|
defer fw.mu.Unlock()
|
||||||
|
fw.wf = append(fw.wf, fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fw *FileWatcher) Prepend(fn func(string)) {
|
||||||
|
fw.mu.Lock()
|
||||||
|
defer fw.mu.Unlock()
|
||||||
|
fw.wf = append([]func(string){fn}, fw.wf...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fw *FileWatcher) Watch() error {
|
||||||
watcher, err := fsnotify.NewWatcher()
|
watcher, err := fsnotify.NewWatcher()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fw.mu.Lock()
|
||||||
fw.watcher = watcher
|
fw.watcher = watcher
|
||||||
|
fw.mu.Unlock()
|
||||||
|
|
||||||
// Start listening for events.
|
// Start listening for events.
|
||||||
go func() {
|
go func() {
|
||||||
@@ -44,7 +99,12 @@ func (fw *FileWatcher) Watch(paths []string) error {
|
|||||||
}
|
}
|
||||||
log.Println("event:", event)
|
log.Println("event:", event)
|
||||||
if !event.Has(fsnotify.Chmod) {
|
if !event.Has(fsnotify.Chmod) {
|
||||||
fw.events <- event.Name
|
time.Sleep(50 * time.Millisecond)
|
||||||
|
fw.mu.Lock()
|
||||||
|
for _, wf := range fw.wf {
|
||||||
|
wf(event.Name)
|
||||||
|
}
|
||||||
|
fw.mu.Unlock()
|
||||||
}
|
}
|
||||||
case err, ok := <-watcher.Errors:
|
case err, ok := <-watcher.Errors:
|
||||||
if !ok {
|
if !ok {
|
||||||
@@ -55,21 +115,23 @@ func (fw *FileWatcher) Watch(paths []string) error {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
for _, path := range paths {
|
|
||||||
err = watcher.Add(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fw *FileWatcher) GetEvents() chan string {
|
// INFO: After closing the watcher, you can't use it anymore.
|
||||||
return fw.events
|
// Also, after a restart, you need to re add the paths
|
||||||
|
func (fw *FileWatcher) Close() {
|
||||||
|
fw.mu.Lock()
|
||||||
|
defer fw.mu.Unlock()
|
||||||
|
|
||||||
|
if fw.watcher != nil {
|
||||||
|
fw.watcher.Close()
|
||||||
|
}
|
||||||
|
fw.watcher = nil
|
||||||
|
fw.paths = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fw *FileWatcher) Close() {
|
func (fw *FileWatcher) Restart() {
|
||||||
fw.watcher.Close()
|
fw.Close()
|
||||||
close(fw.events)
|
fw.Watch()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,7 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/fs"
|
"log"
|
||||||
"path/filepath"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -47,6 +46,8 @@ type Server struct {
|
|||||||
running chan bool
|
running chan bool
|
||||||
shutdown *sync.WaitGroup
|
shutdown *sync.WaitGroup
|
||||||
cache *memory.Storage
|
cache *memory.Storage
|
||||||
|
|
||||||
|
watcher *helpers.FileWatcher
|
||||||
}
|
}
|
||||||
|
|
||||||
func Start(k *app.KGPZ, c *providers.ConfigProvider) *Server {
|
func Start(k *app.KGPZ, c *providers.ConfigProvider) *Server {
|
||||||
@@ -55,33 +56,23 @@ func Start(k *app.KGPZ, c *providers.ConfigProvider) *Server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// INFO: this is a hacky way to add watchers to the server, which will restart the server if the files change
|
func (s *Server) Watcher() error {
|
||||||
// It is very rudimentary and just restarts everything
|
watcher, err := helpers.NewFileWatcher()
|
||||||
// TODO: send a reload on a websocket
|
s.watcher = watcher
|
||||||
func (e *Server) AddWatchers(paths []string) error {
|
s.watcher.Append(func(path string) {
|
||||||
var dirs []string
|
log.Println("Restarting server")
|
||||||
for _, path := range paths {
|
s.Restart()
|
||||||
// Get all subdirectories for paths
|
})
|
||||||
filepath.WalkDir(path, func(path string, d fs.DirEntry, err error) error {
|
|
||||||
if d.IsDir() {
|
|
||||||
dirs = append(dirs, path)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
watcher, err := helpers.NewFileWatcher(dirs)
|
err = s.watcher.RecursiveDir(ROUTES_FILEPATH)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
err = s.watcher.RecursiveDir(LAYOUT_FILEPATH)
|
||||||
w := watcher.GetEvents()
|
if err != nil {
|
||||||
<-w
|
return err
|
||||||
watcher.Close()
|
}
|
||||||
time.Sleep(200 * time.Millisecond)
|
|
||||||
e.Restart()
|
|
||||||
}()
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -149,7 +140,7 @@ func (s *Server) Start() {
|
|||||||
s.runner(srv)
|
s.runner(srv)
|
||||||
|
|
||||||
if s.Config.Debug {
|
if s.Config.Debug {
|
||||||
err := s.AddWatchers([]string{ROUTES_FILEPATH, LAYOUT_FILEPATH})
|
err := s.Watcher()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
{{ define "body" }}
|
{{ define "body" }}
|
||||||
<p>Changed again! Hello from body</p>
|
<p>Change! Hello from body</p>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|||||||
Reference in New Issue
Block a user