513 lines
16 KiB
Go
513 lines
16 KiB
Go
package httpserver
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"time"
|
|
|
|
// "time"
|
|
|
|
"log"
|
|
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
|
betSvc "github.com/SamuelTariku/FortuneBet-Backend/internal/services/bet"
|
|
|
|
enetpulse "github.com/SamuelTariku/FortuneBet-Backend/internal/services/enet_pulse"
|
|
eventsvc "github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
|
|
notificationservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/notification"
|
|
oddssvc "github.com/SamuelTariku/FortuneBet-Backend/internal/services/odds"
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/report"
|
|
resultsvc "github.com/SamuelTariku/FortuneBet-Backend/internal/services/result"
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/stats"
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/ticket"
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/virtualGame/veli"
|
|
"github.com/robfig/cron/v3"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
func StartBetAPIDataFetchingCrons(
|
|
eventService *eventsvc.Service,
|
|
oddsService oddssvc.ServiceImpl,
|
|
resultService *resultsvc.Service,
|
|
mongoLogger *zap.Logger,
|
|
) {
|
|
c := cron.New(cron.WithSeconds())
|
|
|
|
schedule := []struct {
|
|
spec string
|
|
task func()
|
|
}{
|
|
{
|
|
spec: "0 0 * * * *", // Every 1 hour
|
|
task: func() {
|
|
start := time.Now()
|
|
mongoLogger.Info("[BetAPI Event Fetching Crons] Began fetching upcoming events cron task", zap.Time("timestamp", time.Now()))
|
|
if err := eventService.FetchUpcomingEvents(context.Background()); err != nil {
|
|
mongoLogger.Error("[BetAPI Event Fetching Crons] Failed to fetch upcoming events",
|
|
zap.Time("timestamp", time.Now()),
|
|
zap.Duration("duration", time.Since(start)),
|
|
zap.Error(err),
|
|
)
|
|
} else {
|
|
mongoLogger.Info("[BetAPI Event Fetching Crons] Completed fetching upcoming events without errors",
|
|
zap.Time("timestamp", time.Now()),
|
|
zap.Duration("duration", time.Since(start)),
|
|
)
|
|
}
|
|
},
|
|
},
|
|
{
|
|
spec: "0 0 * * * *", // Every 1 hour (since its takes that long to fetch all the events)
|
|
task: func() {
|
|
start := time.Now()
|
|
mongoLogger.Info("[BetAPI Pre-Match Odds Fetching Crons] Began fetching pre-match odds cron task",
|
|
zap.Time("timestamp", time.Now()),
|
|
)
|
|
if err := oddsService.FetchNonLiveOdds(context.Background()); err != nil {
|
|
mongoLogger.Error("[BetAPI Pre-Match Odds Fetching Crons] Failed to fetch pre-match odds",
|
|
zap.Error(err),
|
|
zap.Time("timestamp", time.Now()),
|
|
zap.Duration("duration", time.Since(start)),
|
|
)
|
|
} else {
|
|
mongoLogger.Info("[BetAPI Pre-Match Odds Fetching Crons] Completed fetching pre-match odds without errors",
|
|
zap.Time("timestamp", time.Now()),
|
|
zap.Duration("duration", time.Since(start)),
|
|
)
|
|
}
|
|
},
|
|
},
|
|
{
|
|
spec: "0 */5 * * * *", // Every 5 Minutes
|
|
task: func() {
|
|
start := time.Now()
|
|
mongoLogger.Info("[BetAPI Check And Update Expired Events Crons] Began update all expired events status cron task",
|
|
zap.Time("timestamp", time.Now()),
|
|
)
|
|
if _, err := resultService.CheckAndUpdateExpiredB365Events(context.Background()); err != nil {
|
|
mongoLogger.Error("[BetAPI Check And Update Expired Events Crons] Failed to update expired events status",
|
|
zap.Error(err),
|
|
zap.Time("timestamp", time.Now()),
|
|
zap.Duration("duration", time.Since(start)),
|
|
)
|
|
} else {
|
|
mongoLogger.Info("[BetAPI Check And Update Expired Events Crons] Completed expired events without errors",
|
|
zap.Time("timestamp", time.Now()),
|
|
zap.Duration("duration", time.Since(start)),
|
|
)
|
|
}
|
|
},
|
|
},
|
|
{
|
|
spec: "0 */15 * * * *", // Every 15 Minutes
|
|
task: func() {
|
|
start := time.Now()
|
|
mongoLogger.Info("[BetAPI Fetch Result and Update Bets Crons] Began updating bets based on event results cron task")
|
|
if err := resultService.FetchB365ResultAndUpdateBets(context.Background()); err != nil {
|
|
mongoLogger.Error("[BetAPI Fetch Result and Update Bets Crons] Failed to process result",
|
|
zap.Error(err),
|
|
zap.Time("timestamp", time.Now()),
|
|
zap.Duration("duration", time.Since(start)),
|
|
)
|
|
} else {
|
|
mongoLogger.Info("[BetAPI Fetch Result and Update Bets Crons] Completed processing all event result outcomes without errors",
|
|
zap.Time("timestamp", time.Now()),
|
|
zap.Duration("duration", time.Since(start)),
|
|
)
|
|
}
|
|
},
|
|
},
|
|
{
|
|
spec: "0 0 0 * * 1", // Every Monday
|
|
task: func() {
|
|
mongoLogger.Info("[BetAPI Send Result Notification Crons] Began Send weekly result notification cron task",
|
|
zap.Time("timestamp", time.Now()),
|
|
)
|
|
if err := resultService.CheckAndSendResultNotifications(context.Background(), time.Now().Add(-7*24*time.Hour)); err != nil {
|
|
mongoLogger.Error("[BetAPI Send Result Notification Crons] Failed to process result",
|
|
zap.Time("timestamp", time.Now()),
|
|
zap.Error(err),
|
|
)
|
|
} else {
|
|
mongoLogger.Info("[BetAPI Send Result Notification Crons] Completed sending weekly result notification without errors",
|
|
zap.Time("timestamp", time.Now()),
|
|
)
|
|
}
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, job := range schedule {
|
|
// job.task()
|
|
if _, err := c.AddFunc(job.spec, job.task); err != nil {
|
|
mongoLogger.Error("[BetAPI Data Fetching Crons] Failed to schedule data fetching cron job",
|
|
zap.Time("timestamp", time.Now()),
|
|
zap.Error(err),
|
|
)
|
|
}
|
|
}
|
|
|
|
c.Start()
|
|
mongoLogger.Info("[BetAPI Data Fetching Crons] Started Data Fetching Cron jobs",
|
|
zap.Time("timestamp", time.Now()),
|
|
)
|
|
}
|
|
|
|
func StartCleanupCrons(ticketService ticket.Service, notificationSvc *notificationservice.Service, mongoLogger *zap.Logger) {
|
|
c := cron.New(cron.WithSeconds())
|
|
|
|
schedule := []struct {
|
|
spec string
|
|
task func()
|
|
}{
|
|
{
|
|
spec: "0 0 * * * *", // Every hour
|
|
task: func() {
|
|
mongoLogger.Info("[Delete Old Ticket Crons] Deleting old tickets", zap.Time("timestamp", time.Now()))
|
|
if err := ticketService.DeleteOldTickets(context.Background()); err != nil {
|
|
mongoLogger.Error("[Delete Old Ticket Crons] Failed to remove old ticket",
|
|
zap.Error(err),
|
|
zap.Time("timestamp", time.Now()),
|
|
)
|
|
} else {
|
|
mongoLogger.Info("[Delete Old Ticket Crons] Successfully deleted old tickets",
|
|
zap.Time("timestamp", time.Now()),
|
|
)
|
|
}
|
|
},
|
|
},
|
|
{
|
|
spec: "0 0 0 * * 1", // Every Monday (Weekly)
|
|
task: func() {
|
|
mongoLogger.Info("[Delete Old Notification Crons] Deleting old notifications")
|
|
if err := notificationSvc.DeleteOldNotifications(context.Background()); err != nil {
|
|
mongoLogger.Error("Failed to remove old notifications",
|
|
zap.Time("timestamp", time.Now()),
|
|
zap.Error(err),
|
|
)
|
|
} else {
|
|
mongoLogger.Info("[Delete Old Notification Crons] Successfully deleted old notifications",
|
|
zap.Time("timestamp", time.Now()),
|
|
)
|
|
}
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, job := range schedule {
|
|
if _, err := c.AddFunc(job.spec, job.task); err != nil {
|
|
mongoLogger.Error("[Start Cleanup Crons] Failed to schedule cleanup cron job",
|
|
zap.Time("timestamp", time.Now()),
|
|
zap.Error(err),
|
|
)
|
|
}
|
|
}
|
|
|
|
c.Start()
|
|
mongoLogger.Info("[Start Cleanup Crons] Started cleanup cron jobs",
|
|
zap.Time("timestamp", time.Now()),
|
|
)
|
|
}
|
|
|
|
func StartStatCrons(statService *stats.Service, mongoLogger *zap.Logger) {
|
|
c := cron.New(cron.WithSeconds())
|
|
|
|
schedule := []struct {
|
|
spec string
|
|
task func()
|
|
}{
|
|
{
|
|
spec: "0 0 * * * *", // Every hour
|
|
task: func() {
|
|
start := time.Now()
|
|
mongoLogger.Info("[Company Stats Crons] Updating company stats", zap.Time("timestamp", time.Now()))
|
|
if err := statService.UpdateCompanyStats(context.Background()); err != nil {
|
|
mongoLogger.Error("[Company Stats Crons] Failed to update company stats",
|
|
zap.Error(err),
|
|
zap.Time("timestamp", time.Now()),
|
|
zap.Duration("duration", time.Since(start)),
|
|
)
|
|
} else {
|
|
mongoLogger.Info("[Company Stats Crons] Successfully updated company stats",
|
|
zap.Time("timestamp", time.Now()),
|
|
zap.Duration("duration", time.Since(start)),
|
|
)
|
|
}
|
|
},
|
|
},
|
|
{
|
|
spec: "0 0 * * * *", // Every hour
|
|
task: func() {
|
|
start := time.Now()
|
|
mongoLogger.Info("[Branch Stats Crons] Updating branch stats", zap.Time("timestamp", time.Now()))
|
|
if err := statService.UpdateBranchStats(context.Background()); err != nil {
|
|
mongoLogger.Error("[Branch Stats Crons] Failed to update branch stats",
|
|
zap.Error(err),
|
|
zap.Time("timestamp", time.Now()),
|
|
zap.Duration("duration", time.Since(start)),
|
|
)
|
|
} else {
|
|
mongoLogger.Info("[Branch Stats Crons] Successfully updated branch stats",
|
|
zap.Time("timestamp", time.Now()),
|
|
zap.Duration("duration", time.Since(start)),
|
|
)
|
|
}
|
|
},
|
|
},
|
|
{
|
|
spec: "0 0 * * * *", // Every hour
|
|
task: func() {
|
|
start := time.Now()
|
|
mongoLogger.Info("[Wallet Stats Crons] Updating wallet stats", zap.Time("timestamp", time.Now()))
|
|
if err := statService.UpdateWalletStats(context.Background()); err != nil {
|
|
mongoLogger.Error("[Wallet Stats Crons] Failed to update wallet stats",
|
|
zap.Error(err),
|
|
zap.Time("timestamp", time.Now()),
|
|
zap.Duration("duration", time.Since(start)),
|
|
)
|
|
} else {
|
|
mongoLogger.Info("[Wallet Stats Crons] Successfully updated wallet stats",
|
|
zap.Time("timestamp", time.Now()),
|
|
zap.Duration("duration", time.Since(start)),
|
|
)
|
|
}
|
|
},
|
|
},
|
|
{
|
|
spec: "0 0 * * * *", // Hourly
|
|
task: func() {
|
|
start := time.Now()
|
|
mongoLogger.Info("[Event Stats Crons] Updating event stats")
|
|
if err := statService.UpdateEventBetStats(context.Background()); err != nil {
|
|
mongoLogger.Error("[Event Stats Crons] Failed to update event bet stats",
|
|
zap.Error(err),
|
|
zap.Time("timestamp", time.Now()),
|
|
zap.Duration("duration", time.Since(start)),
|
|
)
|
|
} else {
|
|
mongoLogger.Info("[Event Stats Crons] Successfully updated event stats",
|
|
zap.Time("timestamp", time.Now()),
|
|
zap.Duration("duration", time.Since(start)))
|
|
}
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, job := range schedule {
|
|
job.task()
|
|
if _, err := c.AddFunc(job.spec, job.task); err != nil {
|
|
mongoLogger.Error("[Starting Stats Crons] Failed to schedule stats cron job",
|
|
zap.Error(err),
|
|
zap.Time("timestamp", time.Now()),
|
|
)
|
|
}
|
|
}
|
|
|
|
c.Start()
|
|
mongoLogger.Info("Starting Stats Crons] Started Stat Cron Jobs", zap.Time("timestamp", time.Now()))
|
|
}
|
|
|
|
func StartReportCrons(reportService report.ReportService, mongoLogger *zap.Logger) {
|
|
c := cron.New(cron.WithSeconds())
|
|
|
|
schedule := []struct {
|
|
spec string
|
|
task func()
|
|
}{
|
|
{
|
|
spec: "0 * * * * *", // Every 5 Minutes
|
|
task: func() {
|
|
mongoLogger.Info("[Process Report Crons] Started Checking and Processing Reports")
|
|
if err := reportService.ProcessReportRequests(context.Background()); err != nil {
|
|
mongoLogger.Error("[Process Report Crons] Failed to process reports",
|
|
zap.Error(err),
|
|
)
|
|
} else {
|
|
mongoLogger.Info("[Process Report Crons] Successfully processed all reports")
|
|
}
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, job := range schedule {
|
|
job.task()
|
|
if _, err := c.AddFunc(job.spec, job.task); err != nil {
|
|
mongoLogger.Error("[Report Crons] Failed to schedule report cron job",
|
|
zap.Time("timestamp", time.Now()),
|
|
zap.Error(err),
|
|
)
|
|
}
|
|
}
|
|
|
|
c.Start()
|
|
mongoLogger.Info("[Report Crons] Cron jobs started for reports", zap.Time("timestamp", time.Now()))
|
|
}
|
|
|
|
// SetupReportCronJobs schedules periodic report generation
|
|
func SetupReportandVirtualGameCronJobs(
|
|
ctx context.Context,
|
|
reportService report.ReportService,
|
|
virtualGameService *veli.Service, // inject your virtual game service
|
|
outputDir string,
|
|
) {
|
|
c := cron.New(cron.WithSeconds()) // use WithSeconds for testing
|
|
|
|
schedule := []struct {
|
|
spec string
|
|
period string
|
|
}{
|
|
// {
|
|
// spec: "*/60 * * * * *", // Every 1 minute for testing
|
|
// period: "test",
|
|
// },
|
|
{
|
|
spec: "0 0 0 * * *", // Daily at midnight
|
|
period: "daily",
|
|
},
|
|
}
|
|
|
|
for _, job := range schedule {
|
|
period := job.period
|
|
|
|
if _, err := c.AddFunc(job.spec, func() {
|
|
log.Printf("[%s] Running virtual game fetch & store job...", period)
|
|
|
|
brandID := os.Getenv("VELI_BRAND_ID")
|
|
if brandID == "" {
|
|
log.Println("VELI_BRAND_ID not set, skipping virtual game sync")
|
|
return
|
|
}
|
|
|
|
req := domain.ProviderRequest{
|
|
BrandID: brandID,
|
|
ExtraData: true,
|
|
Size: 1000,
|
|
Page: 1,
|
|
}
|
|
|
|
allGames, err := virtualGameService.FetchAndStoreAllVirtualGames(ctx, req, "ETB")
|
|
if err != nil {
|
|
log.Printf("[%s] Error fetching/storing virtual games: %v", period, err)
|
|
return
|
|
}
|
|
|
|
log.Printf("[%s] Successfully fetched & stored %d virtual games", period, len(allGames))
|
|
|
|
// --- Generate reports only for daily runs ---
|
|
// if period == "daily" {
|
|
// now := time.Now()
|
|
// from := time.Date(now.Year(), now.Month(), now.Day()-1, 0, 0, 0, 0, now.Location())
|
|
// to := time.Date(now.Year(), now.Month(), now.Day()-1, 23, 59, 59, 0, now.Location())
|
|
|
|
// log.Printf("Running daily report for period %s -> %s", from.Format(time.RFC3339), to.Format(time.RFC3339))
|
|
// if err := reportService.GenerateReport(ctx, from, to); err != nil {
|
|
// log.Printf("Error generating daily report: %v", err)
|
|
// } else {
|
|
// log.Printf("Successfully generated daily report")
|
|
// }
|
|
// }
|
|
}); err != nil {
|
|
log.Fatalf("Failed to schedule %s cron job: %v", period, err)
|
|
}
|
|
}
|
|
|
|
c.Start()
|
|
log.Printf("Cron jobs started. Reports will be saved to: %s", outputDir)
|
|
}
|
|
|
|
func ProcessBetCashback(ctx context.Context, betService *betSvc.Service) {
|
|
c := cron.New(cron.WithSeconds())
|
|
|
|
schedule := []struct {
|
|
spec string
|
|
task func()
|
|
}{
|
|
{
|
|
spec: "0 0 0 * * *", // Daily at midnight
|
|
task: func() {
|
|
log.Println("process bet cashbacks...")
|
|
if err := betService.ProcessBetCashback(ctx); err != nil {
|
|
log.Printf("Failed to process bet cashbacks: %v", err)
|
|
} else {
|
|
log.Printf("Successfully processed bet cashbacks")
|
|
}
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, job := range schedule {
|
|
if _, err := c.AddFunc(job.spec, job.task); err != nil {
|
|
log.Fatalf("Failed to schedule cron job: %v", err)
|
|
}
|
|
}
|
|
|
|
c.Start()
|
|
log.Println("Cron jobs started for bet cashbacks")
|
|
}
|
|
|
|
func StartEnetPulseCron(enetPulseSvc *enetpulse.Service, mongoLogger *zap.Logger) {
|
|
c := cron.New(cron.WithSeconds())
|
|
|
|
schedule := []struct {
|
|
spec string
|
|
task func()
|
|
}{
|
|
{
|
|
spec: "0 0,10,20,30,40,50 * * * *", // Every 10 minutes
|
|
task: func() {
|
|
mongoLogger.Info("Began fetching and storing sports cron task")
|
|
if err := enetPulseSvc.FetchAndStoreSports(context.Background()); err != nil {
|
|
mongoLogger.Error("Failed to fetch and store sports",
|
|
zap.Error(err),
|
|
)
|
|
} else {
|
|
mongoLogger.Info("Completed fetching and storing sports without errors")
|
|
}
|
|
|
|
mongoLogger.Info("Began fetching and storing tournament templates cron task")
|
|
if err := enetPulseSvc.FetchAndStoreTournamentTemplates(context.Background()); err != nil {
|
|
mongoLogger.Error("Failed to fetch and store tournament templates",
|
|
zap.Error(err),
|
|
)
|
|
} else {
|
|
mongoLogger.Info("Completed fetching and storing tournament templates without errors")
|
|
}
|
|
|
|
mongoLogger.Info("Began fetching and storing tournaments cron task")
|
|
if err := enetPulseSvc.FetchAndStoreTournaments(context.Background()); err != nil {
|
|
mongoLogger.Error("Failed to fetch and store tournaments",
|
|
zap.Error(err),
|
|
)
|
|
} else {
|
|
mongoLogger.Info("Completed fetching and storing tournaments without errors")
|
|
}
|
|
|
|
mongoLogger.Info("Began fetching and storing tournament stages cron task")
|
|
if err := enetPulseSvc.FetchAndStoreTournamentStages(context.Background()); err != nil {
|
|
mongoLogger.Error("Failed to fetch and store tournament stages",
|
|
zap.Error(err),
|
|
)
|
|
} else {
|
|
mongoLogger.Info("Completed fetching and storing tournament stages without errors")
|
|
}
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, job := range schedule {
|
|
// Run the task immediately at startup
|
|
job.task()
|
|
|
|
// Schedule the task
|
|
if _, err := c.AddFunc(job.spec, job.task); err != nil {
|
|
mongoLogger.Error("Failed to schedule EnetPulse cron job",
|
|
zap.Error(err),
|
|
)
|
|
}
|
|
}
|
|
|
|
c.Start()
|
|
log.Println("EnetPulse cron jobs started for sports, tournament templates, tournaments, and tournament stages")
|
|
mongoLogger.Info("EnetPulse cron jobs started for sports, tournament templates, tournaments, and tournament stages")
|
|
}
|