Notice configuration changes and restart the watchers.

This commit is contained in:
Justin Hawkins 2021-10-10 13:43:36 +10:30
parent 90f8c3588b
commit fd6f6884ee
4 changed files with 146 additions and 25 deletions

View File

@ -38,7 +38,8 @@ type ConfigV2 struct {
} }
type ConfigService struct { type ConfigService struct {
Config ConfigV2 Config *ConfigV2
Changed chan bool
ConfigFilename string ConfigFilename string
} }
@ -57,7 +58,7 @@ func (c *ConfigService) LoadOrInit() error {
if os.IsNotExist(err) { if os.IsNotExist(err) {
daulog.SendLog("NOTE: No config file, writing out sample configuration", daulog.LogTypeInfo) daulog.SendLog("NOTE: No config file, writing out sample configuration", daulog.LogTypeInfo)
daulog.SendLog("You need to set the configuration via the web interface", daulog.LogTypeInfo) daulog.SendLog("You need to set the configuration via the web interface", daulog.LogTypeInfo)
c.Config = *DefaultConfig() c.Config = DefaultConfig()
return c.Save() return c.Save()
} else { } else {
return c.Load() return c.Load()
@ -158,6 +159,7 @@ func (c *ConfigService) Save() error {
if err != nil { if err != nil {
return fmt.Errorf("cannot save config %s: %s", c.ConfigFilename, err.Error()) return fmt.Errorf("cannot save config %s: %s", c.ConfigFilename, err.Error())
} }
return nil return nil
} }

46
dau.go
View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"context"
"encoding/json" "encoding/json"
"flag" "flag"
"fmt" "fmt"
@ -39,8 +40,10 @@ func main() {
parseOptions() parseOptions()
// grab the config // grab the config, register to notice changes
config := config.DefaultConfigService() config := config.DefaultConfigService()
configChanged := make(chan bool)
config.Changed = configChanged
config.LoadOrInit() config.LoadOrInit()
// create the uploader // create the uploader
@ -48,26 +51,41 @@ func main() {
// log.Print("Opening web browser") // log.Print("Opening web browser")
// open.Start("http://localhost:9090") // open.Start("http://localhost:9090")
web := web.WebService{Config: *config} web := web.WebService{Config: config}
web.StartWebServer() web.StartWebServer()
go func() { checkUpdates() }() go func() { checkUpdates() }()
// create the watchers // create the watchers, restart them if config changes
// blocks forever
startWatchers(config, &up, configChanged)
log.Printf("Conf: %#v", config.Config)
for _, c := range config.Config.Watchers {
log.Printf("Creating watcher for %v", c)
watcher := watch{uploader: up, lastCheck: time.Now(), newLastCheck: time.Now(), config: c}
go watcher.Watch(config.Config.WatchInterval)
} }
select {} func startWatchers(config *config.ConfigService, up *upload.Uploader, configChange chan bool) {
}
func (w *watch) Watch(interval int) {
for { for {
log.Printf("Creating watchers")
ctx, cancel := context.WithCancel(context.Background())
for _, c := range config.Config.Watchers {
log.Printf("Creating watcher for %s interval %d", c.Path, config.Config.WatchInterval)
watcher := watch{uploader: *up, lastCheck: time.Now(), newLastCheck: time.Now(), config: c}
go watcher.Watch(config.Config.WatchInterval, ctx)
}
// wait for single that the config changed
<-configChange
cancel()
log.Printf("starting new watchers due to config change")
}
}
func (w *watch) Watch(interval int, ctx context.Context) {
for {
select {
case <-ctx.Done():
log.Printf("Killing old watcher")
return
default:
newFiles := w.ProcessNewFiles() newFiles := w.ProcessNewFiles()
for _, f := range newFiles { for _, f := range newFiles {
w.uploader.AddFile(f, w.config) w.uploader.AddFile(f, w.config)
@ -78,6 +96,7 @@ func (w *watch) Watch(interval int) {
time.Sleep(time.Duration(interval) * time.Second) time.Sleep(time.Duration(interval) * time.Second)
} }
} }
}
// ProcessNewFiles returns an array of new files that have appeared since // ProcessNewFiles returns an array of new files that have appeared since
// the last time ProcessNewFiles was run. // the last time ProcessNewFiles was run.
@ -119,7 +138,6 @@ func (w *watch) checkPath() bool {
// If the file is eligible, not excluded and new enough to care we add it // If the file is eligible, not excluded and new enough to care we add it
// to the passed in array of files // to the passed in array of files
func (w *watch) checkFile(path string, found *[]string, exclusions []string) error { func (w *watch) checkFile(path string, found *[]string, exclusions []string) error {
log.Printf("Considering %s", path)
extension := strings.ToLower(filepath.Ext(path)) extension := strings.ToLower(filepath.Ext(path))

96
dau_test.go Normal file
View File

@ -0,0 +1,96 @@
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"testing"
"time"
"github.com/tardisx/discord-auto-upload/config"
"github.com/tardisx/discord-auto-upload/upload"
)
func TestWatchNewFiles(t *testing.T) {
dir := createFileTree()
defer os.RemoveAll(dir)
time.Sleep(time.Second)
w := watch{
config: config.Watcher{Path: dir},
uploader: upload.Uploader{},
lastCheck: time.Now(),
newLastCheck: time.Now(),
}
files := w.ProcessNewFiles()
if len(files) != 0 {
t.Errorf("was not zero files (%d): %v", len(files), files)
}
// create a new file
os.Create(fmt.Sprintf("%s%c%s", dir, os.PathSeparator, "b.gif"))
files = w.ProcessNewFiles()
if len(files) != 1 {
t.Error("was not one file")
}
if files[0] != fmt.Sprintf("%s%c%s", dir, os.PathSeparator, "b.gif") {
t.Error("wrong file")
}
}
func TestExclsion(t *testing.T) {
dir := createFileTree()
defer os.RemoveAll(dir)
time.Sleep(time.Second)
w := watch{
config: config.Watcher{Path: dir, Exclude: []string{"thumb", "tiny"}},
uploader: upload.Uploader{},
lastCheck: time.Now(),
newLastCheck: time.Now(),
}
files := w.ProcessNewFiles()
if len(files) != 0 {
t.Errorf("was not zero files (%d): %v", len(files), files)
}
// create a new file that would not hit exclusion, and two that would
os.Create(fmt.Sprintf("%s%c%s", dir, os.PathSeparator, "b.gif"))
os.Create(fmt.Sprintf("%s%c%s", dir, os.PathSeparator, "b_thumb.gif"))
os.Create(fmt.Sprintf("%s%c%s", dir, os.PathSeparator, "tiny_b.jpg"))
files = w.ProcessNewFiles()
if len(files) != 1 {
t.Error("was not one new file")
}
}
func TestCheckPath(t *testing.T) {
dir := createFileTree()
defer os.RemoveAll(dir)
w := watch{
config: config.Watcher{Path: dir},
uploader: upload.Uploader{},
lastCheck: time.Now(),
newLastCheck: time.Now(),
}
if !w.checkPath() {
t.Error("checkPath failed?")
}
os.RemoveAll(dir)
if w.checkPath() {
t.Error("checkPath succeeded when shouldn't?")
}
}
func createFileTree() string {
dir, err := ioutil.TempDir("", "dau-test")
if err != nil {
log.Fatal(err)
}
os.Create(fmt.Sprintf("%s%c%s", dir, os.PathSeparator, "a.gif"))
os.Create(fmt.Sprintf("%s%c%s", dir, os.PathSeparator, "a.jpg"))
os.Create(fmt.Sprintf("%s%c%s", dir, os.PathSeparator, "a.png"))
return dir
}

View File

@ -18,7 +18,7 @@ import (
) )
type WebService struct { type WebService struct {
Config config.ConfigService Config *config.ConfigService
} }
//go:embed data //go:embed data
@ -129,7 +129,7 @@ func (ws *WebService) handleConfig(w http.ResponseWriter, r *http.Request) {
w.Write(j) w.Write(j)
return return
} }
ws.Config.Config = newConfig ws.Config.Config = &newConfig
err = ws.Config.Save() err = ws.Config.Save()
if err != nil { if err != nil {
w.WriteHeader(400) w.WriteHeader(400)
@ -138,6 +138,11 @@ func (ws *WebService) handleConfig(w http.ResponseWriter, r *http.Request) {
return return
} }
// config has changed, so tell the world
if ws.Config.Changed != nil {
ws.Config.Changed <- true
}
} }
b, _ := json.Marshal(ws.Config.Config) b, _ := json.Marshal(ws.Config.Config)