2022-10-20 16:58:21 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"GoWeb/config"
|
|
|
|
"GoWeb/database"
|
2024-07-10 22:45:04 +00:00
|
|
|
"GoWeb/internal"
|
|
|
|
"GoWeb/internal/models"
|
|
|
|
"GoWeb/internal/routes"
|
2023-12-23 03:03:15 +00:00
|
|
|
"GoWeb/templating"
|
2023-02-18 00:25:14 +00:00
|
|
|
"context"
|
2023-02-05 18:46:47 +00:00
|
|
|
"embed"
|
2023-08-03 17:13:37 +00:00
|
|
|
"errors"
|
2023-08-18 02:13:17 +00:00
|
|
|
"log/slog"
|
2022-10-20 16:58:21 +00:00
|
|
|
"net/http"
|
|
|
|
"os"
|
2023-02-18 00:25:14 +00:00
|
|
|
"os/signal"
|
|
|
|
"syscall"
|
2022-12-05 00:04:24 +00:00
|
|
|
"time"
|
2022-10-20 16:58:21 +00:00
|
|
|
)
|
|
|
|
|
2024-07-10 22:45:04 +00:00
|
|
|
//go:embed internal/frontend/templates internal/frontend/static
|
2023-02-05 18:46:47 +00:00
|
|
|
var res embed.FS
|
|
|
|
|
2022-10-20 16:58:21 +00:00
|
|
|
func main() {
|
2024-07-02 02:19:48 +00:00
|
|
|
// Create instance of Deps
|
|
|
|
appLoaded := app.Deps{}
|
2022-10-20 16:58:21 +00:00
|
|
|
|
|
|
|
// Load config file to application
|
2022-12-05 00:04:24 +00:00
|
|
|
appLoaded.Config = config.LoadConfig()
|
2022-10-20 16:58:21 +00:00
|
|
|
|
2023-02-05 18:46:47 +00:00
|
|
|
// Load templates
|
|
|
|
appLoaded.Res = &res
|
|
|
|
|
2022-11-01 21:30:54 +00:00
|
|
|
// Create logs directory if it doesn't exist
|
|
|
|
if _, err := os.Stat("logs"); os.IsNotExist(err) {
|
2022-12-05 00:04:24 +00:00
|
|
|
err := os.Mkdir("logs", 0755)
|
|
|
|
if err != nil {
|
2023-09-03 20:56:35 +00:00
|
|
|
panic("failed to create log directory: " + err.Error())
|
2022-12-05 00:04:24 +00:00
|
|
|
}
|
2022-11-01 21:30:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Create log file and set output
|
2023-08-18 02:13:17 +00:00
|
|
|
file, err := os.OpenFile("logs/"+time.Now().Format("2006-01-02")+".log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
|
|
|
|
if err != nil {
|
2023-09-03 20:56:35 +00:00
|
|
|
panic("error creating log file: " + err.Error())
|
2023-08-18 02:13:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
logger := slog.New(slog.NewTextHandler(file, nil))
|
|
|
|
slog.SetDefault(logger) // Set structured logger globally
|
2022-10-20 16:58:21 +00:00
|
|
|
|
2023-02-14 05:41:45 +00:00
|
|
|
// Connect to database and run migrations
|
2023-08-03 17:09:40 +00:00
|
|
|
appLoaded.Db = database.Connect(&appLoaded)
|
2023-02-14 05:41:45 +00:00
|
|
|
if appLoaded.Config.Db.AutoMigrate {
|
|
|
|
err = models.RunAllMigrations(&appLoaded)
|
|
|
|
if err != nil {
|
2023-08-18 02:13:17 +00:00
|
|
|
slog.Error("error running migrations: " + err.Error())
|
|
|
|
os.Exit(1)
|
2023-02-14 05:41:45 +00:00
|
|
|
}
|
|
|
|
}
|
2022-10-20 16:58:21 +00:00
|
|
|
|
2023-04-04 19:37:36 +00:00
|
|
|
// Assign and run scheduled tasks
|
|
|
|
appLoaded.ScheduledTasks = app.Scheduled{
|
2024-07-02 02:19:48 +00:00
|
|
|
EveryReboot: []func(app *app.Deps){models.ScheduledSessionCleanup},
|
|
|
|
EveryMinute: []func(app *app.Deps){models.ScheduledSessionCleanup},
|
2023-04-04 19:37:36 +00:00
|
|
|
}
|
|
|
|
|
2022-10-20 16:58:21 +00:00
|
|
|
// Define Routes
|
2023-08-03 17:09:40 +00:00
|
|
|
routes.Get(&appLoaded)
|
|
|
|
routes.Post(&appLoaded)
|
2022-10-20 16:58:21 +00:00
|
|
|
|
2023-12-23 03:03:15 +00:00
|
|
|
// Prepare templates
|
|
|
|
err = templating.BuildPages(&appLoaded)
|
|
|
|
if err != nil {
|
|
|
|
slog.Error("error building templates: " + err.Error())
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
2022-10-20 16:58:21 +00:00
|
|
|
// Start server
|
2023-02-18 00:25:14 +00:00
|
|
|
server := &http.Server{Addr: appLoaded.Config.Listen.Ip + ":" + appLoaded.Config.Listen.Port}
|
|
|
|
go func() {
|
2023-09-03 20:56:35 +00:00
|
|
|
slog.Info("starting server and listening on " + appLoaded.Config.Listen.Ip + ":" + appLoaded.Config.Listen.Port)
|
2023-02-18 00:25:14 +00:00
|
|
|
err := server.ListenAndServe()
|
2023-08-03 17:13:37 +00:00
|
|
|
if err != nil && !errors.Is(err, http.ErrServerClosed) {
|
2023-09-03 20:56:35 +00:00
|
|
|
slog.Error("could not listen on %s: %v\n", appLoaded.Config.Listen.Ip+":"+appLoaded.Config.Listen.Port, err)
|
2023-08-18 02:13:17 +00:00
|
|
|
os.Exit(1)
|
2023-02-18 00:25:14 +00:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
// Wait for interrupt signal and shut down the server
|
|
|
|
interrupt := make(chan os.Signal, 1)
|
|
|
|
signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM)
|
2023-04-04 19:37:36 +00:00
|
|
|
stop := make(chan struct{})
|
|
|
|
go app.RunScheduledTasks(&appLoaded, 100, stop)
|
2023-04-06 17:01:29 +00:00
|
|
|
|
2023-02-18 00:25:14 +00:00
|
|
|
<-interrupt
|
2023-09-03 20:56:35 +00:00
|
|
|
slog.Info("interrupt signal received. Shutting down server...")
|
2023-02-18 00:25:14 +00:00
|
|
|
|
|
|
|
err = server.Shutdown(context.Background())
|
2022-10-20 16:58:21 +00:00
|
|
|
if err != nil {
|
2023-09-03 20:56:35 +00:00
|
|
|
slog.Error("could not gracefully shutdown the server: %v\n", err)
|
2023-08-18 02:13:17 +00:00
|
|
|
os.Exit(1)
|
2022-10-20 16:58:21 +00:00
|
|
|
}
|
|
|
|
}
|