Files
tm_back/pkg/schedule/cron.go
T
n.nakhostin cc3d6163ed Refactor Tender Management to Introduce Notice Entity and Repository
- Replaced the tender repository with a new notice repository, encapsulating notice-related data access methods.
- Introduced the Notice entity to represent tender/contract notices, including relevant fields and methods for managing notice data.
- Updated the TED scraper to utilize the new notice repository for creating and managing notices, enhancing the integration with the tender management system.
- Implemented Ollama SDK initialization in the web bootstrap process, allowing for improved AI interactions.
- Enhanced the tender service to include Ollama SDK for additional functionality, ensuring a more robust service layer.
2025-10-04 15:22:49 +03:30

145 lines
3.9 KiB
Go

package schedule
import (
"time"
"tm/internal/notice"
"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
noticeRepo notice.Repository
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, noticeRepo notice.Repository) *CronScheduler {
// Create cron with timezone support and seconds precision
c := cron.New(cron.WithLocation(time.UTC), cron.WithSeconds())
return &CronScheduler{
cron: c,
mongoManager: mongoManager,
noticeRepo: noticeRepo,
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,
// })
}