141 lines
3.2 KiB
Go
141 lines
3.2 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"embed"
|
|
"fmt"
|
|
"html/template"
|
|
"log/slog"
|
|
"net/http"
|
|
"os"
|
|
"os/signal"
|
|
"time"
|
|
|
|
"github.com/golang-migrate/migrate/v4"
|
|
_ "github.com/golang-migrate/migrate/v4/database/pgx/v5"
|
|
"github.com/golang-migrate/migrate/v4/source/iofs"
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
|
|
"git.lastassault.de/speatzle/morffix/config"
|
|
)
|
|
|
|
var conf config.Config
|
|
|
|
var templates *template.Template
|
|
|
|
var funcMap = template.FuncMap{
|
|
"sub": sub,
|
|
}
|
|
|
|
func sub(a, b int) int {
|
|
return a - b
|
|
}
|
|
|
|
var db *pgxpool.Pool
|
|
|
|
func Start(_conf config.Config, tmplFS embed.FS, staticFS embed.FS, migrationsFS embed.FS, resetDB bool) {
|
|
conf = _conf
|
|
|
|
// Static Files
|
|
staticServer := http.FS(staticFS)
|
|
fs := http.FileServer(staticServer)
|
|
|
|
// Templates
|
|
t := template.New("")
|
|
t.Funcs(funcMap)
|
|
t, err := t.ParseFS(tmplFS, "tmpl/*.tmpl")
|
|
if err != nil {
|
|
panic(fmt.Errorf("Parsing templates: %w", err))
|
|
}
|
|
templates = t
|
|
|
|
slog.Info("Connecting to Database...")
|
|
db, err = pgxpool.New(context.Background(), "postgres://"+conf.Server.Database)
|
|
if err != nil {
|
|
slog.Error("Unable to create connection pool", "err", err)
|
|
return
|
|
}
|
|
defer db.Close()
|
|
slog.Info("Connected to Database, Starting Migration")
|
|
|
|
driver, err := iofs.New(migrationsFS, "migrations")
|
|
if err != nil {
|
|
slog.Error("Unable to Create Migration Driver", "err", err)
|
|
return
|
|
}
|
|
|
|
m, err := migrate.NewWithSourceInstance("iofs", driver, "pgx5://"+conf.Server.Database)
|
|
if err != nil {
|
|
slog.Error("Unable to Setup migration", "err", err)
|
|
return
|
|
}
|
|
|
|
if resetDB {
|
|
slog.Info("Running Down Migrations...")
|
|
err = m.Down()
|
|
if err != nil {
|
|
slog.Error("Unable to Migrate Down", "err", err)
|
|
return
|
|
}
|
|
}
|
|
|
|
//err = m.Down()
|
|
err = m.Up()
|
|
if err == migrate.ErrNoChange {
|
|
slog.Info("No Migrations Required")
|
|
} else if err != nil {
|
|
slog.Error("Unable to Migrate", "err", err)
|
|
return
|
|
} else {
|
|
slog.Info("Migration Done")
|
|
}
|
|
|
|
mux := http.NewServeMux()
|
|
mux.HandleFunc("/worker", handleWorkerWebsocket)
|
|
mux.Handle("/static/", fs)
|
|
mux.HandleFunc("/tasks", handleTasks)
|
|
mux.HandleFunc("/files/{id}", handleFile)
|
|
mux.HandleFunc("/tasks/{id}", handleTask)
|
|
mux.HandleFunc("/scan/{id}", handleScan)
|
|
mux.HandleFunc("/libraries/{id}", handleLibrary)
|
|
mux.HandleFunc("/libraries", handleLibraries)
|
|
mux.HandleFunc("/", handleIndex)
|
|
|
|
server := &http.Server{
|
|
Addr: conf.Server.Address,
|
|
Handler: mux,
|
|
ReadTimeout: 10 * time.Second,
|
|
WriteTimeout: 10 * time.Second,
|
|
IdleTimeout: 30 * time.Second,
|
|
ReadHeaderTimeout: 10 * time.Second,
|
|
}
|
|
|
|
serverClose := make(chan bool)
|
|
go func() {
|
|
slog.Info("Listening...", "Address", conf.Server.Address)
|
|
err := server.ListenAndServe()
|
|
if err != http.ErrServerClosed {
|
|
slog.Error("Listen Failed", "err", err)
|
|
} else {
|
|
slog.Info("Server Closed")
|
|
}
|
|
serverClose <- true
|
|
}()
|
|
|
|
stopCleanup := make(chan bool, 1)
|
|
go manageWorkers(stopCleanup)
|
|
|
|
sigs := make(chan os.Signal, 1)
|
|
signal.Notify(sigs, os.Interrupt)
|
|
select {
|
|
case <-serverClose:
|
|
slog.Info("Exiting due to Listen Failure")
|
|
case sig := <-sigs:
|
|
slog.Info("Stopping Server...", "signal", sig)
|
|
stopCtx, cancel := context.WithTimeout(context.Background(), time.Second*10)
|
|
server.Shutdown(stopCtx)
|
|
cancel()
|
|
stopCleanup <- true
|
|
slog.Info("Done")
|
|
}
|
|
}
|