linstrom/main.go
mstar 6cc699cbbd
All checks were successful
/ docker (push) Successful in 4m4s
Clean up unused code and better shutdown in main
2025-05-22 16:56:56 +02:00

152 lines
3.9 KiB
Go

// TODO: Add EUPL banner everywhere
package main
import (
"embed"
"flag"
"fmt"
"net/http"
"os"
"os/signal"
"path"
"sync"
"git.mstar.dev/mstar/goutils/other"
"github.com/rs/zerolog/log"
"gopkg.in/natefinch/lumberjack.v2"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"git.mstar.dev/mstar/linstrom/config"
"git.mstar.dev/mstar/linstrom/shared"
storagenew "git.mstar.dev/mstar/linstrom/storage-new"
"git.mstar.dev/mstar/linstrom/storage-new/dbgen"
webdebug "git.mstar.dev/mstar/linstrom/web/debug"
webpublic "git.mstar.dev/mstar/linstrom/web/public"
)
// TODO: Add frontend overwrite
// Serve frontend files from a given directory instead of embedded data
//go:embed frontend-reactive/dist/* frontend-reactive/dist/assets
var reactiveFS embed.FS
//go:embed frontend-noscript
var nojsFS embed.FS
//go:embed duck.webp
var defaultDuck string
//go:embed duck.webp
var duckFS embed.FS
func main() {
_ = reactiveFS
_ = nojsFS
other.SetupFlags()
flag.Parse()
logfile := getLogFilePathOrNil()
if logfile == nil {
other.ConfigureLogging(nil)
log.Warn().Msg("Can't write to target logfile, not creating one")
} else {
other.ConfigureLogging(&lumberjack.Logger{
Filename: *logfile,
MaxSize: 500, // Megabytes
MaxBackups: 3,
MaxAge: 3, // Days
Compress: false,
})
log.Info().Str("logfile", *logfile).Msg("Logging to stderr and logfile")
}
if err := config.ReadAndWriteToGlobal(*shared.FlagConfigFile); err != nil {
log.Fatal().
Err(err).
Str("config-file", *shared.FlagConfigFile).
Msg("Failed to read config and couldn't write default")
}
log.Trace().Any("config", config.GlobalConfig).Msg("Full config")
// Request to only check config
if *shared.FlagConfigOnly {
return
}
newServer()
}
func getLogFilePathOrNil() *string {
logfile := *shared.FlagLogFile
logPath := path.Dir(logfile)
if shared.IsWritable(logPath) {
return &logfile
} else {
return nil
}
}
func newServer() {
log.Info().Msg("Connecting to db")
db, err := gorm.Open(
postgres.Open(config.GlobalConfig.Storage.BuildPostgresDSN()),
&gorm.Config{
Logger: shared.NewGormLogger(log.Logger),
},
)
if err != nil {
log.Fatal().Err(err).Msg("Failed to start db")
}
dbgen.SetDefault(db)
log.Info().Msg("Applying migrations")
if err = storagenew.Migrate(db); err != nil {
log.Fatal().Err(err).Msg("Failed to automigrate structure")
}
log.Info().Msg("Inserting self into db")
if err = storagenew.InsertSelf(); err != nil {
log.Fatal().Err(err).Msg("Failed to insert self properly")
}
log.Info().Msg("Inserting placeholder/unknown user")
if err = storagenew.InsertUnknownActorPlaceholder(); err != nil {
log.Fatal().Err(err).Msg("Failed to insert self properly")
}
debugShutdownChan := make(chan *sync.WaitGroup, 1)
interuptChan := make(chan os.Signal, 1)
signal.Notify(interuptChan, os.Interrupt)
if *shared.FlagStartDebugServer {
go func() {
log.Info().Msg("Starting debug server")
s := webdebug.New(*shared.FlagDebugPort)
go func() {
wg := <-debugShutdownChan
if err := s.Stop(); err != nil {
log.Fatal().Err(err).Msg("Failed to cleanly stop debug server")
}
log.Info().Msg("Debug server stopped")
wg.Done()
}()
if err = s.Start(); err != nil && err != http.ErrServerClosed {
log.Fatal().Err(err).Msg("Debug server failed")
}
}()
}
public := webpublic.New(
fmt.Sprintf(":%v", config.GlobalConfig.General.PrivatePort),
&defaultDuck,
duckFS,
)
go func() {
log.Info().Msg("Starting public server")
if err = public.Start(); err != nil && err != http.ErrServerClosed {
log.Fatal().Err(err).Msg("Failed to start public server")
}
}()
<-interuptChan
log.Info().Msg("Received interrupt, shutting down")
wg := sync.WaitGroup{}
wg.Add(1)
debugShutdownChan <- &wg
if err = public.Stop(); err != nil {
log.Fatal().Err(err).Msg("Failed to stop public server")
}
log.Info().Msg("Public server stopped")
wg.Wait()
}