tercul-backend/cmd/api/main.go
google-labs-jules[bot] 8797cec718 Refactor: In-progress refactoring to fix build.
This commit includes the following changes:
- Refactored all data repositories in `internal/data/sql/` to use a consistent `sql` package and to align with the new `domain` models.
- Fixed the GraphQL structure by moving the server creation logic from `internal/app` to `cmd/api`, which resolved an import cycle.
- Corrected numerous incorrect import paths for packages like `graph`, `linguistics`, `syncjob`, and the legacy `models` package.
- Resolved several package and function redeclaration errors.
- Removed legacy migration code.
2025-09-05 15:11:30 +00:00

146 lines
4.5 KiB
Go

package main
import (
"context"
"net/http"
"os"
"os/signal"
"syscall"
"tercul/internal/app"
"tercul/internal/platform/config"
"tercul/internal/platform/log"
"time"
"github.com/99designs/gqlgen/graphql/playground"
"github.com/hibiken/asynq"
graph "tercul/internal/adapters/graphql"
"tercul/internal/platform/auth"
)
// main is the entry point for the Tercul application.
// It uses the ApplicationBuilder and ServerFactory to initialize all components
// and start the servers in a clean, maintainable way.
func main() {
// Load configuration from environment variables
config.LoadConfig()
// Initialize structured logger with appropriate log level
log.SetDefaultLevel(log.InfoLevel)
log.LogInfo("Starting Tercul application",
log.F("environment", config.Cfg.Environment),
log.F("version", "1.0.0"))
// Build application components
appBuilder := app.NewApplicationBuilder()
if err := appBuilder.Build(); err != nil {
log.LogFatal("Failed to build application",
log.F("error", err))
}
defer appBuilder.Close()
// Create server factory
serverFactory := app.NewServerFactory(appBuilder)
// Create servers
backgroundServers, err := serverFactory.CreateBackgroundJobServers()
if err != nil {
log.LogFatal("Failed to create background job servers",
log.F("error", err))
}
// Create GraphQL server
resolver := &graph.Resolver{
WorkRepo: appBuilder.GetRepositories().WorkRepository,
UserRepo: appBuilder.GetRepositories().UserRepository,
AuthorRepo: appBuilder.GetRepositories().AuthorRepository,
TranslationRepo: appBuilder.GetRepositories().TranslationRepository,
CommentRepo: appBuilder.GetRepositories().CommentRepository,
LikeRepo: appBuilder.GetRepositories().LikeRepository,
BookmarkRepo: appBuilder.GetRepositories().BookmarkRepository,
CollectionRepo: appBuilder.GetRepositories().CollectionRepository,
TagRepo: appBuilder.GetRepositories().TagRepository,
CategoryRepo: appBuilder.GetRepositories().CategoryRepository,
WorkService: appBuilder.GetServices().WorkService,
Localization: appBuilder.GetServices().LocalizationService,
AuthService: appBuilder.GetServices().AuthService,
}
jwtManager := auth.NewJWTManager()
srv := graph.NewServerWithAuth(resolver, jwtManager)
graphQLServer := &http.Server{
Addr: config.Cfg.ServerPort,
Handler: srv,
}
log.LogInfo("GraphQL server created successfully", log.F("port", config.Cfg.ServerPort))
// Create GraphQL playground
playgroundHandler := playground.Handler("GraphQL", "/query")
playgroundServer := &http.Server{
Addr: config.Cfg.PlaygroundPort,
Handler: playgroundHandler,
}
log.LogInfo("GraphQL playground created successfully", log.F("port", config.Cfg.PlaygroundPort))
// Start HTTP servers in goroutines
go func() {
log.LogInfo("Starting GraphQL server",
log.F("port", config.Cfg.ServerPort))
if err := graphQLServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.LogFatal("Failed to start GraphQL server",
log.F("error", err))
}
}()
go func() {
log.LogInfo("Starting GraphQL playground",
log.F("port", config.Cfg.PlaygroundPort))
if err := playgroundServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.LogFatal("Failed to start GraphQL playground",
log.F("error", err))
}
}()
// Start background job servers in goroutines
for i, server := range backgroundServers {
go func(serverIndex int, srv *asynq.Server) {
log.LogInfo("Starting background job server",
log.F("serverIndex", serverIndex))
if err := srv.Run(asynq.NewServeMux()); err != nil {
log.LogError("Background job server failed",
log.F("serverIndex", serverIndex),
log.F("error", err))
}
}(i, server)
}
// Wait for interrupt signal to gracefully shutdown the servers
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
log.LogInfo("Shutting down servers...")
// Graceful shutdown
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := graphQLServer.Shutdown(ctx); err != nil {
log.LogError("GraphQL server forced to shutdown",
log.F("error", err))
}
if err := playgroundServer.Shutdown(ctx); err != nil {
log.LogError("GraphQL playground forced to shutdown",
log.F("error", err))
}
// Shutdown background job servers
for i, server := range backgroundServers {
server.Shutdown()
log.LogInfo("Background job server shutdown",
log.F("serverIndex", i))
}
log.LogInfo("All servers shutdown successfully")
}