Files
tm_back/pkg/schedule/cron.go
T
n.nakhostin 05c7eae8a2 Add TED Scraper Configuration and Cron Scheduler Implementation
- Introduced a new configuration file for the TED scraper, defining database connection settings, logging preferences, and scraping parameters.
- Implemented a CronScheduler to manage scheduled tasks for TED operations, utilizing the robfig/cron library for scheduling.
- Added new entities and structures for handling TED XML data, including eForms and tender-related information, enhancing the scraper's functionality.
- Updated the main application to initialize the TED scraper with the new configuration and set up graceful shutdown handling.
- Removed the deprecated scraping implementation to streamline the codebase and focus on the new architecture.
2025-09-30 16:03:53 +03:30

145 lines
3.9 KiB
Go

package schedule
import (
"time"
"tm/internal/tender"
"tm/pkg/logger"
"tm/pkg/mongo"
"github.com/robfig/cron/v3"
)
// CronScheduler handles scheduled tasks for TED operations
type CronScheduler struct {
cron *cron.Cron
mongoManager *mongo.ConnectionManager
tenderRepo tender.TenderRepository
logger logger.Logger
}
// Logger interface for structured logging
type Logger interface {
Info(msg string, fields map[string]interface{})
Error(msg string, fields map[string]interface{})
Debug(msg string, fields map[string]interface{})
}
type Job struct {
Name string
Func func()
Expr string
}
// NewCronScheduler creates a new cron scheduler instance
func NewCronScheduler(logger logger.Logger, mongoManager *mongo.ConnectionManager, tenderRepo tender.TenderRepository) *CronScheduler {
// Create cron with timezone support and seconds precision
c := cron.New(cron.WithLocation(time.UTC), cron.WithSeconds())
return &CronScheduler{
cron: c,
mongoManager: mongoManager,
tenderRepo: tenderRepo,
logger: logger,
}
}
// Start starts the cron scheduler
func (cs *CronScheduler) Start() {
cs.logger.Info("Starting TED cron scheduler", map[string]interface{}{})
cs.cron.Start()
}
// Stop stops the cron scheduler gracefully
func (cs *CronScheduler) Stop() {
cs.logger.Info("Stopping TED cron scheduler", map[string]interface{}{})
ctx := cs.cron.Stop()
<-ctx.Done()
}
// ScheduleDailyJob schedules a job to run daily at 10:00 AM UTC
func (cs *CronScheduler) AddJob(job Job) error {
// Cron expression: "0 0 10 * * *" means:
// Second: 0
// Minute: 0
// Hour: 10 (10 AM)
// Day of month: * (every day)
// Month: * (every month)
// Day of week: * (every day of week)
_, err := cs.cron.AddFunc(job.Expr, func() {
now := time.Now().Local()
cs.logger.Info("Starting daily TED job", map[string]interface{}{
"job_name": job.Name,
"cron_expression": job.Expr,
"time": time.Now().Format(time.RFC3339),
})
job.Func()
cs.logger.Info("Completed job successfully", map[string]interface{}{
"time": now.Format(time.RFC3339),
"job_name": job.Name,
"cron_expression": job.Expr,
})
})
if err != nil {
cs.logger.Error("Failed to schedule daily job", map[string]interface{}{
"error": err.Error(),
"job_name": job.Name,
"cron_expression": job.Expr,
"time": time.Now().Format(time.RFC3339),
})
return err
}
cs.logger.Info("Daily job scheduled successfully", map[string]interface{}{
"job_name": job.Name,
"cron_expression": job.Expr,
"time": time.Now().Format(time.RFC3339),
})
return nil
}
// ExampleTEDScrapingJob is an example job function that can be scheduled
func ExampleTEDScrapingJob() {
// now := time.Now().Local()
// // Example: Get current date for TED scraping
// currentDate := time.Now().Format("02/01/2006")
// currentYear := time.Now().Year()
// // This is just an example - replace with actual TED scraping logic
// ojs, err := GetOJS(currentYear, currentDate)
// if err != nil {
// log.Printf("Error getting OJS: %v", err)
// return
// }
// log.Printf("Successfully retrieved OJS: %s for date: %s", ojs, currentDate)
// Add your actual TED scraping/processing logic here
// ojs, err := GetOJS(now.Year(), now.Format("02/01/2006"))
// if err != nil {
// cs.logger.Error("Failed to get OJS", map[string]interface{}{
// "error": err.Error(),
// })
// return
// }
// scraper := NewTEDScraper(cs.config, cs.logger, cs.mongoManager, cs.tenderRepo)
// result, err := scraper.DownloadDailyPackage(context.Background(), ojs)
// if err != nil {
// cs.logger.Error("Failed to download daily package", map[string]interface{}{
// "error": err.Error(),
// })
// return
// }
// cs.logger.Info("Downloaded daily package successfully", map[string]interface{}{
// "result": result,
// "time": now.Format(time.RFC3339),
// "ojs": ojs,
// })
}