376 lines
12 KiB
Go
376 lines
12 KiB
Go
package httpserver
|
||
|
||
import (
|
||
"context"
|
||
"os"
|
||
"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/ticket"
|
||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/virtualGame/orchestration"
|
||
"github.com/robfig/cron/v3"
|
||
"go.uber.org/zap"
|
||
)
|
||
|
||
func StartDataFetchingCrons(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() {
|
||
mongoLogger.Info("Began fetching upcoming events cron task")
|
||
if err := eventService.FetchUpcomingEvents(context.Background()); err != nil {
|
||
mongoLogger.Error("Failed to fetch upcoming events",
|
||
zap.Error(err),
|
||
)
|
||
} else {
|
||
mongoLogger.Info("Completed fetching upcoming events without errors")
|
||
}
|
||
},
|
||
},
|
||
{
|
||
spec: "0 0 * * * *", // Every 1 hour (since its takes that long to fetch all the events)
|
||
task: func() {
|
||
mongoLogger.Info("Began fetching non live odds cron task")
|
||
if err := oddsService.FetchNonLiveOdds(context.Background()); err != nil {
|
||
mongoLogger.Error("Failed to fetch non live odds",
|
||
zap.Error(err),
|
||
)
|
||
} else {
|
||
mongoLogger.Info("Completed fetching non live odds without errors")
|
||
}
|
||
},
|
||
},
|
||
{
|
||
spec: "0 */5 * * * *", // Every 5 Minutes
|
||
task: func() {
|
||
mongoLogger.Info("Began update all expired events status cron task")
|
||
if _, err := resultService.CheckAndUpdateExpiredB365Events(context.Background()); err != nil {
|
||
mongoLogger.Error("Failed to update expired events status",
|
||
zap.Error(err),
|
||
)
|
||
} else {
|
||
mongoLogger.Info("Completed expired events without errors")
|
||
}
|
||
},
|
||
},
|
||
{
|
||
spec: "0 */15 * * * *", // Every 15 Minutes
|
||
task: func() {
|
||
mongoLogger.Info("Began updating bets based on event results cron task")
|
||
if err := resultService.FetchB365ResultAndUpdateBets(context.Background()); err != nil {
|
||
mongoLogger.Error("Failed to process result",
|
||
zap.Error(err),
|
||
)
|
||
} else {
|
||
mongoLogger.Info("Completed processing all event result outcomes without errors")
|
||
}
|
||
},
|
||
},
|
||
{
|
||
spec: "0 0 0 * * 1", // Every Monday
|
||
task: func() {
|
||
mongoLogger.Info("Began Send weekly result notification cron task")
|
||
if err := resultService.CheckAndSendResultNotifications(context.Background(), time.Now().Add(-7*24*time.Hour)); err != nil {
|
||
mongoLogger.Error("Failed to process result",
|
||
zap.Error(err),
|
||
)
|
||
} else {
|
||
mongoLogger.Info("Completed sending weekly result notification without errors")
|
||
}
|
||
},
|
||
},
|
||
}
|
||
|
||
for _, job := range schedule {
|
||
// job.task()
|
||
if _, err := c.AddFunc(job.spec, job.task); err != nil {
|
||
mongoLogger.Error("Failed to schedule data fetching cron job",
|
||
zap.Error(err),
|
||
)
|
||
}
|
||
}
|
||
|
||
c.Start()
|
||
log.Println("Cron jobs started for event and odds services")
|
||
mongoLogger.Info("Cron jobs started for event and odds services")
|
||
}
|
||
|
||
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("Deleting old tickets")
|
||
if err := ticketService.DeleteOldTickets(context.Background()); err != nil {
|
||
mongoLogger.Error("Failed to remove old ticket",
|
||
zap.Error(err),
|
||
)
|
||
} else {
|
||
mongoLogger.Info("Successfully deleted old tickets")
|
||
}
|
||
},
|
||
},
|
||
{
|
||
spec: "0 0 0 * * 1", // Every Monday (Weekly)
|
||
task: func() {
|
||
mongoLogger.Info("Deleting old notifications")
|
||
if err := notificationSvc.DeleteOldNotifications(context.Background()); err != nil {
|
||
mongoLogger.Error("Failed to remove old notifications",
|
||
zap.Error(err),
|
||
)
|
||
} else {
|
||
mongoLogger.Info("Successfully deleted old notifications")
|
||
}
|
||
},
|
||
},
|
||
}
|
||
|
||
for _, job := range schedule {
|
||
if _, err := c.AddFunc(job.spec, job.task); err != nil {
|
||
mongoLogger.Error("Failed to schedule ticket cron job",
|
||
zap.Error(err),
|
||
)
|
||
}
|
||
}
|
||
|
||
c.Start()
|
||
mongoLogger.Info("Cron jobs started for ticket service")
|
||
}
|
||
|
||
// SetupReportCronJobs schedules periodic report generation
|
||
func SetupReportandVirtualGameCronJobs(
|
||
ctx context.Context,
|
||
reportService *report.Service,
|
||
virtualGameOrchestrationService *orchestration.Service,
|
||
outputDir string,
|
||
) {
|
||
c := cron.New(cron.WithSeconds()) // WithSeconds for testing, remove in prod
|
||
|
||
schedule := []struct {
|
||
spec string
|
||
period string
|
||
}{
|
||
// { spec: "*/60 * * * * *", period: "test" }, // every 60 seconds for testing
|
||
{
|
||
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 & provider report job...", period)
|
||
|
||
brandID := os.Getenv("VELI_BRAND_ID")
|
||
if brandID == "" {
|
||
log.Println("VELI_BRAND_ID not set, skipping virtual game sync")
|
||
return
|
||
}
|
||
|
||
// Step 1. Fetch and store all virtual games
|
||
req := domain.ProviderRequest{
|
||
BrandID: brandID,
|
||
ExtraData: true,
|
||
Size: 1000,
|
||
Page: 1,
|
||
}
|
||
|
||
allGames, err := virtualGameOrchestrationService.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))
|
||
|
||
// Step 2. Fetch all providers
|
||
providers, total, err := virtualGameOrchestrationService.ListProviders(ctx, 1000, 0)
|
||
if err != nil {
|
||
log.Printf("[%s] Failed to list providers: %v", period, err)
|
||
return
|
||
} else if total == 0 {
|
||
log.Printf("[%s] No providers found, skipping report generation", period)
|
||
return
|
||
}
|
||
|
||
log.Printf("[%s] Found %d total providers", period, total)
|
||
|
||
// Step 3. Create provider-level daily report entries
|
||
reportDate := time.Now().UTC().Truncate(24 * time.Hour)
|
||
for _, p := range providers {
|
||
createReq := domain.CreateVirtualGameProviderReport{
|
||
ProviderID: p.ProviderID,
|
||
ReportDate: reportDate,
|
||
TotalGamesPlayed: 0,
|
||
TotalBets: 0,
|
||
TotalPayouts: 0,
|
||
TotalPlayers: 0,
|
||
ReportType: period, // "daily"
|
||
}
|
||
|
||
_, err := virtualGameOrchestrationService.CreateVirtualGameProviderReport(ctx, createReq)
|
||
if err != nil {
|
||
log.Printf("[%s] Failed to create report for provider %s: %v", period, p.ProviderID, err)
|
||
continue
|
||
}
|
||
|
||
log.Printf("[%s] Created daily report row for provider: %s", period, p.ProviderID)
|
||
}
|
||
|
||
log.Printf("[%s] Daily provider reports created successfully", period)
|
||
|
||
}); 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 */2 * * *", // Every 2 hours
|
||
task: func() {
|
||
ctx := context.Background()
|
||
|
||
// 1️⃣ Sports
|
||
mongoLogger.Info("Began fetching and storing sports cron task")
|
||
if err := enetPulseSvc.FetchAndStoreSports(ctx); err != nil {
|
||
mongoLogger.Error("Failed to fetch and store sports", zap.Error(err))
|
||
} else {
|
||
mongoLogger.Info("\n\n✅ Completed fetching and storing sports\n\n")
|
||
}
|
||
|
||
// 2️⃣ Tournament Templates
|
||
mongoLogger.Info("Began fetching and storing tournament templates cron task")
|
||
if err := enetPulseSvc.FetchAndStoreTournamentTemplates(ctx); err != nil {
|
||
mongoLogger.Error("Failed to fetch and store tournament templates", zap.Error(err))
|
||
} else {
|
||
mongoLogger.Info("\n\n✅ Completed fetching and storing tournament templates\n\n")
|
||
}
|
||
|
||
// 3️⃣ Tournaments
|
||
mongoLogger.Info("Began fetching and storing tournaments cron task")
|
||
if err := enetPulseSvc.FetchAndStoreTournaments(ctx); err != nil {
|
||
mongoLogger.Error("Failed to fetch and store tournaments", zap.Error(err))
|
||
} else {
|
||
mongoLogger.Info("\n\n✅ Completed fetching and storing tournaments\n\n")
|
||
}
|
||
|
||
// 4️⃣ Tournament Stages
|
||
// mongoLogger.Info("Began fetching and storing tournament stages cron task")
|
||
// if err := enetPulseSvc.FetchAndStoreTournamentStages(ctx); err != nil {
|
||
// mongoLogger.Error("Failed to fetch and store tournament stages", zap.Error(err))
|
||
// } else {
|
||
// mongoLogger.Info("✅ \n\nCompleted fetching and storing tournament stages\n\n")
|
||
// }
|
||
|
||
// // 5️⃣ Fixtures
|
||
mongoLogger.Info("Began fetching and storing fixtures cron task")
|
||
today := time.Now().Format("2006-01-02")
|
||
if err := enetPulseSvc.FetchAndStoreFixtures(ctx, today); err != nil {
|
||
mongoLogger.Error("Failed to fetch and store fixtures", zap.Error(err))
|
||
} else {
|
||
mongoLogger.Info("\n\n✅ Completed fetching and storing fixtures\n\n")
|
||
}
|
||
|
||
// 6️⃣ Results
|
||
// mongoLogger.Info("Began fetching and storing results cron task")
|
||
// if err := enetPulseSvc.FetchAndStoreResults(ctx); err != nil {
|
||
// mongoLogger.Error("Failed to fetch and store results", zap.Error(err))
|
||
// } else {
|
||
// mongoLogger.Info("\n\n✅ Completed fetching and storing results\n\n")
|
||
// }
|
||
|
||
// 7 Outcome Types
|
||
mongoLogger.Info("Began fetching and storing outcome_types cron task")
|
||
if err := enetPulseSvc.FetchAndStoreOutcomeTypes(ctx); err != nil {
|
||
mongoLogger.Error("Failed to fetch and store outcome_types", zap.Error(err))
|
||
} else {
|
||
mongoLogger.Info("\n\n✅ Completed fetching and storing outcome_types\n\n")
|
||
}
|
||
|
||
// 8 Preodds
|
||
mongoLogger.Info("Began fetching and storing preodds cron task")
|
||
if err := enetPulseSvc.FetchAndStorePreodds(ctx); err != nil {
|
||
mongoLogger.Error("Failed to fetch and store preodds", zap.Error(err))
|
||
} else {
|
||
mongoLogger.Info("\n\n✅ Completed fetching and storing preodds\n\n")
|
||
}
|
||
},
|
||
},
|
||
}
|
||
|
||
for _, job := range schedule {
|
||
// Run 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, tournament stages, fixtures, and results")
|
||
mongoLogger.Info("EnetPulse cron jobs started for sports, tournament templates, tournaments, tournament stages, fixtures, and results")
|
||
}
|