0747908873
- Introduced AlertMail configuration in both scraper and worker bootstrap files, allowing for customizable email notifications. - Updated the TED scraper to utilize the AlertMail configuration for sending completion notifications, improving flexibility in notification management. - Enhanced error logging in the worker's main function to capture issues when listing Ollama models, ensuring better visibility into potential failures. - Refactored notification sending logic to check for a valid AlertMail before dispatching emails, ensuring notifications are only sent when configured. - Improved overall structure and readability of the bootstrap configuration files, aligning with best practices for maintainability.
186 lines
5.2 KiB
Go
186 lines
5.2 KiB
Go
package bootstrap
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
"time"
|
|
"tm/internal/notice"
|
|
"tm/pkg/config"
|
|
"tm/pkg/logger"
|
|
"tm/pkg/mongo"
|
|
"tm/pkg/notification"
|
|
"tm/pkg/schedule"
|
|
"tm/ted"
|
|
)
|
|
|
|
// Init Application Configuration
|
|
func InitConfig() (*Config, error) {
|
|
conf, err := config.LoadConfig(".", &Config{})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to load config: %v", err)
|
|
}
|
|
|
|
return conf, nil
|
|
}
|
|
|
|
// Init Logger Service
|
|
func InitLogger(conf config.LoggingConfig) logger.Logger {
|
|
return logger.NewLogger(&logger.Config{
|
|
Level: conf.Level,
|
|
Format: conf.Format,
|
|
Output: conf.Output,
|
|
File: logger.FileConfig{
|
|
Path: conf.File.Path,
|
|
MaxSize: conf.File.MaxSize,
|
|
MaxBackups: conf.File.MaxBackups,
|
|
MaxAge: conf.File.MaxAge,
|
|
Compress: conf.File.Compress,
|
|
},
|
|
})
|
|
}
|
|
|
|
// Init MongoDB Connection Manager
|
|
func InitMongoDB(conf config.MongoConfig, log logger.Logger) *mongo.ConnectionManager {
|
|
// Convert infra.MongoConfig to mongo.ConnectionConfig
|
|
connectionConfig := mongo.ConnectionConfig{
|
|
URI: conf.URI,
|
|
Database: conf.Name,
|
|
MaxPoolSize: uint64(conf.MaxPoolSize),
|
|
MinPoolSize: 5, // Default minimum pool size
|
|
MaxConnIdleTime: 30 * time.Minute, // Default idle time
|
|
ConnectTimeout: conf.Timeout,
|
|
ServerSelectionTimeout: 5 * time.Second, // Default server selection timeout
|
|
}
|
|
|
|
// Create MongoDB connection manager
|
|
connectionManager, err := mongo.NewConnectionManager(connectionConfig, log)
|
|
if err != nil {
|
|
log.Error("Failed to initialize MongoDB connection", map[string]interface{}{
|
|
"error": err.Error(),
|
|
"uri": conf.URI,
|
|
"db": conf.Name,
|
|
})
|
|
panic(fmt.Sprintf("Failed to initialize MongoDB connection: %v", err))
|
|
}
|
|
|
|
log.Info("MongoDB connection manager initialized successfully", map[string]interface{}{
|
|
"database": conf.Name,
|
|
"uri": conf.URI,
|
|
"pool_size": conf.MaxPoolSize,
|
|
})
|
|
|
|
return connectionManager
|
|
}
|
|
|
|
// init TED scraper
|
|
func InitTEDScraper(config Config, mongoManager *mongo.ConnectionManager, appLogger logger.Logger, notify notification.SDK) {
|
|
// Initialize tender repository
|
|
noticeRepo := notice.NewRepository(mongoManager, appLogger)
|
|
|
|
// Initialize TED scraper
|
|
tedScraper := ted.NewTEDScraper(
|
|
&ted.Config{
|
|
BaseURL: config.TED.BaseURL,
|
|
Timeout: config.TED.Timeout,
|
|
MaxRetries: config.TED.MaxRetries,
|
|
RetryDelay: config.TED.RetryDelay,
|
|
UserAgent: config.TED.UserAgent,
|
|
MaxConcurrency: config.TED.MaxConcurrency,
|
|
DownloadDir: config.TED.DownloadDir,
|
|
CleanupAfter: config.TED.CleanupAfter,
|
|
ScrapingInterval: config.TED.ScrapingInterval,
|
|
AlertMail: config.AlertMail,
|
|
},
|
|
appLogger,
|
|
mongoManager,
|
|
noticeRepo,
|
|
notify,
|
|
)
|
|
|
|
// start TED scraper job
|
|
schedule.NewCronScheduler(appLogger, mongoManager, noticeRepo).AddJob(schedule.Job{
|
|
Name: "TED Scraper Job",
|
|
Func: func() {
|
|
_ = tedScraper.Run(context.Background())
|
|
},
|
|
Expr: config.TED.ScrapingInterval,
|
|
})
|
|
|
|
// Create context with cancellation
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
|
|
// Set up signal handling for graceful shutdown
|
|
signalChan := make(chan os.Signal, 1)
|
|
signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
|
|
|
|
// Start the scraper in a goroutine
|
|
scraperDone := make(chan error, 1)
|
|
go func() {
|
|
appLogger.Info("Starting TED scraper", map[string]interface{}{
|
|
"interval": config.TED.ScrapingInterval,
|
|
})
|
|
scraperDone <- tedScraper.Run(ctx)
|
|
}()
|
|
|
|
// Wait for shutdown signal or scraper completion
|
|
select {
|
|
case <-signalChan:
|
|
appLogger.Info("Received shutdown signal, stopping scraper...", map[string]interface{}{})
|
|
cancel()
|
|
|
|
// Wait for scraper to finish gracefully with timeout
|
|
shutdownTimeout := time.NewTimer(30 * time.Second)
|
|
select {
|
|
case <-scraperDone:
|
|
appLogger.Info("Scraper stopped gracefully", map[string]interface{}{})
|
|
case <-shutdownTimeout.C:
|
|
appLogger.Warn("Scraper shutdown timeout, forcing exit", map[string]interface{}{})
|
|
}
|
|
|
|
case err := <-scraperDone:
|
|
|
|
if err != nil {
|
|
appLogger.Error("Scraper finished with error", map[string]interface{}{
|
|
"error": err.Error(),
|
|
})
|
|
os.Exit(1)
|
|
}
|
|
appLogger.Info("Scraper finished successfully", map[string]interface{}{})
|
|
}
|
|
}
|
|
|
|
// Init Notification Service
|
|
func InitNotificationService(conf config.NotificationConfig, log logger.Logger) notification.SDK {
|
|
notificationConfig := ¬ification.Config{
|
|
BaseURL: conf.BaseURL,
|
|
Timeout: conf.Timeout,
|
|
RetryAttempts: conf.RetryAttempts,
|
|
RetryDelay: conf.RetryDelay,
|
|
EnableLogging: conf.EnableLogging,
|
|
UserAgent: conf.UserAgent,
|
|
}
|
|
|
|
notificationSDK, err := notification.New(notificationConfig, log)
|
|
if err != nil {
|
|
log.Error("Failed to initialize Notification SDK", map[string]interface{}{
|
|
"error": err.Error(),
|
|
})
|
|
fmt.Printf("Failed to initialize Notification SDK: %v\n", err.Error())
|
|
}
|
|
|
|
log.Info("Notification SDK initialized successfully", map[string]interface{}{
|
|
"base_url": conf.BaseURL,
|
|
"timeout": conf.Timeout,
|
|
"retry_attempts": conf.RetryAttempts,
|
|
"retry_delay": conf.RetryDelay,
|
|
"enable_logging": conf.EnableLogging,
|
|
"user_agent": conf.UserAgent,
|
|
})
|
|
|
|
return *notificationSDK
|
|
}
|