basic online
This commit is contained in:
92
main.go
Normal file
92
main.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"Engine/internal/database"
|
||||
"Engine/internal/handler"
|
||||
"Engine/internal/service"
|
||||
)
|
||||
|
||||
func main() {
|
||||
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
|
||||
|
||||
dbPath := os.Getenv("DB_PATH")
|
||||
if dbPath == "" {
|
||||
dbPath = "fpa.db"
|
||||
}
|
||||
|
||||
db, err := database.Connect(context.Background(), dbPath)
|
||||
if err != nil {
|
||||
logger.Error("failed to open database", "error", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
if err := database.Migrate(db); err != nil {
|
||||
logger.Error("migration failed", "error", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
budgetRepo := database.NewBudgetRepo(db)
|
||||
actualsRepo := database.NewActualsRepo(db)
|
||||
budgetSvc := service.NewBudgetService(budgetRepo)
|
||||
varianceSvc := service.NewVarianceService(budgetRepo, actualsRepo)
|
||||
|
||||
budgetH := handler.NewBudgetHandler(budgetSvc)
|
||||
actualsH := handler.NewActualsHandler(actualsRepo)
|
||||
varianceH := handler.NewVarianceHandler(varianceSvc)
|
||||
|
||||
mux := http.NewServeMux()
|
||||
|
||||
mux.HandleFunc("POST /api/v1/budgets", budgetH.Create)
|
||||
mux.HandleFunc("PUT /api/v1/budgets/{id}", budgetH.Update)
|
||||
mux.HandleFunc("DELETE /api/v1/budgets/{id}", budgetH.Delete)
|
||||
mux.HandleFunc("POST /api/v1/actuals/ingest", actualsH.Ingest)
|
||||
mux.HandleFunc("GET /api/v1/variance", varianceH.Report)
|
||||
mux.HandleFunc("GET /api/v1/variance/alerts", varianceH.Alerts)
|
||||
mux.HandleFunc("GET /api/v1/health", func(w http.ResponseWriter, r *http.Request) {
|
||||
if err := db.PingContext(r.Context()); err != nil {
|
||||
http.Error(w, `{"error":"db unhealthy"}`, http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write([]byte(`{"status":"ok"}`))
|
||||
})
|
||||
|
||||
port := os.Getenv("PORT")
|
||||
if port == "" {
|
||||
port = "8080"
|
||||
}
|
||||
|
||||
srv := &http.Server{
|
||||
Addr: ":" + port,
|
||||
Handler: mux,
|
||||
ReadTimeout: 10 * time.Second,
|
||||
WriteTimeout: 30 * time.Second,
|
||||
IdleTimeout: 120 * time.Second,
|
||||
}
|
||||
|
||||
quit := make(chan os.Signal, 1)
|
||||
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
||||
|
||||
go func() {
|
||||
logger.Info("server starting", "port", port, "db", dbPath)
|
||||
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
logger.Error("server error", "error", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}()
|
||||
|
||||
<-quit
|
||||
logger.Info("shutting down gracefully")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||
defer cancel()
|
||||
srv.Shutdown(ctx)
|
||||
}
|
||||
Reference in New Issue
Block a user