Spaces:
Runtime error
Runtime error
| package main | |
| import ( | |
| "context" | |
| "net/http" | |
| "os" | |
| "os/signal" | |
| "strings" | |
| "syscall" | |
| "time" | |
| "gdelt-engine/internal/api" | |
| "gdelt-engine/internal/config" | |
| "gdelt-engine/internal/console" | |
| "gdelt-engine/internal/processor" | |
| "gdelt-engine/internal/storage" | |
| "go.uber.org/zap" | |
| "go.uber.org/zap/zapcore" | |
| ) | |
| const version = "3.0.0" | |
| func main() { | |
| // Load configuration | |
| cfg := config.Load() | |
| // Initialize loggers | |
| zapLogger := initZapLogger(cfg.LogLevel) | |
| defer zapLogger.Sync() | |
| consoleLog := console.New(version) | |
| // Print startup banner | |
| consoleLog.PrintBanner(false) | |
| consoleLog.Info("Mode: Timestamp-triggered processing with parallel workers") | |
| // Debug: Check if MONGO_URI is set | |
| mongoURI := cfg.MongoURI | |
| if mongoURI == "" || mongoURI == "mongodb://localhost:27017" { | |
| consoleLog.Warn("MONGO_URI not set or using default - check your secrets!") | |
| } else { | |
| // Mask the URI for logging (show first 20 chars only) | |
| masked := mongoURI | |
| if len(masked) > 30 { | |
| masked = masked[:30] + "..." | |
| } | |
| consoleLog.Info("MONGO_URI detected: %s", masked) | |
| } | |
| // Create context with signal handling | |
| ctx, cancel := context.WithCancel(context.Background()) | |
| defer cancel() | |
| // Handle graceful shutdown | |
| sigCh := make(chan os.Signal, 1) | |
| signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) | |
| // Connect to MongoDB | |
| consoleLog.Info("Connecting to MongoDB...") | |
| db, err := storage.NewMongoDB(ctx, cfg.MongoURI, cfg.DatabaseName, zapLogger) | |
| if err != nil { | |
| consoleLog.Fatal("MongoDB connection failed: %v", err) | |
| } | |
| defer func() { | |
| closeCtx, closeCancel := context.WithTimeout(context.Background(), 5*time.Second) | |
| defer closeCancel() | |
| db.Close(closeCtx) | |
| }() | |
| consoleLog.Success("MongoDB connected to %s", cfg.DatabaseName) | |
| // Create processor with worker pool | |
| proc := processor.NewProcessor(db, zapLogger, | |
| processor.WithMaxParallelTimestamps(24), | |
| processor.WithTimeout(5*time.Minute), | |
| processor.WithBatchSize(1000), | |
| ) | |
| consoleLog.Success("Processor initialized") | |
| // Create API handlers | |
| handlers := api.NewHandlers(proc, db.GetStats) | |
| // Create and start API server | |
| apiServer := api.NewServer(cfg.Port, handlers) | |
| go func() { | |
| consoleLog.Info("API server starting on :%s", cfg.Port) | |
| consoleLog.Info("Endpoints:") | |
| consoleLog.Info(" POST /process - Submit timestamps for processing") | |
| consoleLog.Info(" GET /status/{ts} - Check timestamp status") | |
| consoleLog.Info(" GET /timestamps - List all timestamps") | |
| consoleLog.Info(" GET /stats - Database statistics") | |
| consoleLog.Info(" GET /health - Health check") | |
| if err := apiServer.Start(); err != nil && err != http.ErrServerClosed { | |
| consoleLog.Error("API server error: %v", err) | |
| } | |
| }() | |
| consoleLog.Success("Ready - waiting for requests") | |
| // Wait for shutdown signal | |
| sig := <-sigCh | |
| consoleLog.Warn("Shutdown signal received: %s", sig.String()) | |
| // Graceful shutdown | |
| shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 10*time.Second) | |
| defer shutdownCancel() | |
| if err := apiServer.Shutdown(shutdownCtx); err != nil { | |
| consoleLog.Error("API server shutdown error: %v", err) | |
| } | |
| cancel() | |
| consoleLog.Success("Shutdown complete") | |
| } | |
| func initZapLogger(level string) *zap.Logger { | |
| var zapLevel zapcore.Level | |
| switch strings.ToLower(level) { | |
| case "debug": | |
| zapLevel = zapcore.DebugLevel | |
| case "warn": | |
| zapLevel = zapcore.WarnLevel | |
| case "error": | |
| zapLevel = zapcore.ErrorLevel | |
| default: | |
| zapLevel = zapcore.InfoLevel | |
| } | |
| encoderConfig := zap.NewProductionEncoderConfig() | |
| encoderConfig.TimeKey = "ts" | |
| encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder | |
| config := zap.Config{ | |
| Level: zap.NewAtomicLevelAt(zapLevel), | |
| Development: false, | |
| Encoding: "json", | |
| EncoderConfig: encoderConfig, | |
| OutputPaths: []string{"stderr"}, | |
| ErrorOutputPaths: []string{"stderr"}, | |
| } | |
| logger, err := config.Build() | |
| if err != nil { | |
| panic(err) | |
| } | |
| return logger | |
| } | |