From 6b40e0c0fa90f11be14a93f1d6275779fd645cac Mon Sep 17 00:00:00 2001 From: Alan Pearce Date: Mon, 13 May 2024 21:50:14 +0200 Subject: refactor: combine import and web server into one binary --- searchix.go | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 searchix.go (limited to 'searchix.go') diff --git a/searchix.go b/searchix.go new file mode 100644 index 0000000..9a0b16e --- /dev/null +++ b/searchix.go @@ -0,0 +1,116 @@ +package main + +import ( + "flag" + "log" + "log/slog" + "os" + "os/signal" + "sync" + "time" + + "searchix/internal/config" + "searchix/internal/importer" + "searchix/internal/index" + "searchix/internal/server" + + "github.com/pelletier/go-toml/v2" +) + +var ( + configFile = flag.String("config", "config.toml", "config file to use") + liveReload = flag.Bool("live", false, "whether to enable live reloading (development)") + replace = flag.Bool("replace", false, "whether to replace existing database, if it exists") +) + +func nextOccurrenceOfLocalTime(t toml.LocalTime) time.Time { + now := time.Now() + dayTime := t + nextRun := time.Date( + now.Year(), + now.Month(), + now.Day(), + dayTime.Hour, + dayTime.Minute, + dayTime.Second, + 0, + time.Local, + ) + if nextRun.Before(now) { + return nextRun.AddDate(0, 0, 1) + } + + return nextRun +} + +func main() { + flag.Parse() + + conf, err := config.GetConfig(*configFile) + if err != nil { + log.Panicf("error parsing configuration file: %v", err) + } + slog.SetLogLoggerLevel(conf.LogLevel) + log.SetFlags(log.LstdFlags | log.Lmsgprefix) + log.SetPrefix("searchix: ") + + read, write, exists, err := index.OpenOrCreate(conf.DataPath, *replace) + if err != nil { + log.Fatalf("Failed to open or create index: %v", err) + } + + if !exists { + err = importer.Start(conf, write, *replace) + if err != nil { + log.Fatalf("Failed to build index: %v", err) + } + } + + c := make(chan os.Signal, 2) + signal.Notify(c, os.Interrupt) + sv, err := server.New(conf, read, *liveReload) + if err != nil { + log.Fatalf("error setting up server: %v", err) + } + wg := &sync.WaitGroup{} + wg.Add(1) + go func() { + defer wg.Done() + sig := <-c + log.Printf("signal captured: %v", sig) + <-sv.Stop() + slog.Debug("server stopped") + }() + + go func() { + nextRun := nextOccurrenceOfLocalTime(conf.Importer.UpdateAt) + for { + slog.Debug("scheduling next run", "next-run", nextRun) + <-time.After(time.Until(nextRun)) + wg.Add(1) + slog.Info("updating index") + err = importer.Start(conf, write, false) + wg.Done() + if err != nil { + slog.Warn("error updating index", "error", err) + } else { + slog.Info("update complete") + } + nextRun = nextRun.AddDate(0, 0, 1) + } + }() + + sErr := make(chan error) + wg.Add(1) + go func() { + defer wg.Done() + sErr <- sv.Start() + }() + + err = <-sErr + if err != nil { + // Error starting or closing listener: + log.Fatalf("error: %v", err) + } + wg.Wait() +} -- cgit 1.4.1