90 lines
2.1 KiB
Go
90 lines
2.1 KiB
Go
package main
|
|
|
|
import (
|
|
"business-engine/internal/config"
|
|
"business-engine/internal/database"
|
|
"business-engine/internal/payroll"
|
|
"context"
|
|
"log/slog"
|
|
"net/http"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
"time"
|
|
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
)
|
|
|
|
// Server contains all dependencies of the application
|
|
type Server struct {
|
|
config *config.Config
|
|
logger *slog.Logger
|
|
db *pgxpool.Pool
|
|
router *http.ServeMux
|
|
}
|
|
|
|
// NewServer constructs a new server
|
|
func NewServer(cfg *config.Config, logger *slog.Logger) (*Server, error) {
|
|
dbpool, err := pgxpool.New(context.Background(), cfg.DatabaseURL)
|
|
if err != nil {
|
|
logger.Error("failed to connect to database", "error", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
server := &Server{
|
|
config: cfg,
|
|
logger: logger,
|
|
db: dbpool,
|
|
router: http.NewServeMux(),
|
|
}
|
|
|
|
server.setupRoutes()
|
|
|
|
return server, nil
|
|
}
|
|
|
|
// setupRoutes initializes all routes and handlers
|
|
func (s *Server) setupRoutes() {
|
|
employeeRepo := database.New(s.db)
|
|
employeeService := payroll.NewService(employeeRepo, s.logger)
|
|
employeeHandler := payroll.NewEmployeeHandler(*employeeService, s.logger)
|
|
|
|
s.router.HandleFunc("GET /health", func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write([]byte("OK"))
|
|
})
|
|
|
|
s.router.HandleFunc("GET /api/v1/employees", employeeHandler.ListEmployees)
|
|
|
|
s.router.HandleFunc("GET /api/v1/payroll", employeeHandler.RunPayroll)
|
|
}
|
|
|
|
func (s *Server) Start() {
|
|
httpServer := &http.Server{
|
|
Addr: ":" + s.config.Port,
|
|
Handler: s.router,
|
|
}
|
|
|
|
go func() {
|
|
s.logger.Info("server starting", "port", s.config.Port)
|
|
if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
|
s.logger.Error("server failed to start", "error", err)
|
|
os.Exit(1)
|
|
}
|
|
}()
|
|
|
|
stop := make(chan os.Signal, 1)
|
|
signal.Notify(stop, os.Interrupt, syscall.SIGTERM)
|
|
<-stop
|
|
|
|
s.logger.Info("shutting down server gracefully")
|
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
defer cancel()
|
|
|
|
if err := httpServer.Shutdown(ctx); err != nil {
|
|
s.logger.Error("server shutdown failed", "error", err)
|
|
} else {
|
|
s.logger.Info("server stopped")
|
|
}
|
|
}
|