searchix.go (view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 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()
}
|