fixing issues with fetching event

This commit is contained in:
Samuel Tariku 2025-09-17 17:25:49 +03:00
parent 2875e9b85c
commit af1cb4023e
7 changed files with 103 additions and 98 deletions

View File

@ -114,7 +114,7 @@ func main() {
authSvc := authentication.NewService(store, store, cfg.RefreshExpiry) authSvc := authentication.NewService(store, store, cfg.RefreshExpiry)
userSvc := user.NewService(store, store, messengerSvc, cfg) userSvc := user.NewService(store, store, messengerSvc, cfg)
eventSvc := event.New(cfg.Bet365Token, store, *settingSvc, domain.MongoDBLogger) eventSvc := event.New(cfg.Bet365Token, store, *settingSvc, domain.MongoDBLogger, cfg)
oddsSvc := odds.New(store, cfg, eventSvc, logger, domain.MongoDBLogger) oddsSvc := odds.New(store, cfg, eventSvc, logger, domain.MongoDBLogger)
notificationRepo := repository.NewNotificationRepository(store) notificationRepo := repository.NewNotificationRepository(store)
virtuaGamesRepo := repository.NewVirtualGameRepository(store) virtuaGamesRepo := repository.NewVirtualGameRepository(store)

View File

@ -0,0 +1,27 @@
package domain
import (
"encoding/json"
"fmt"
)
// Custom type for fields that can be string or int
type StringOrNumber string
func (s *StringOrNumber) UnmarshalJSON(data []byte) error {
// Try as string
var str string
if err := json.Unmarshal(data, &str); err == nil {
*s = StringOrNumber(str)
return nil
}
// Try as number
var num json.Number
if err := json.Unmarshal(data, &num); err == nil {
*s = StringOrNumber(num.String())
return nil
}
return fmt.Errorf("StringOrNumber: cannot unmarshal %s", string(data))
}

View File

@ -27,7 +27,7 @@ type RawOdd struct {
// The Market ID for the json data can be either string / int which is causing problems when UnMarshalling // The Market ID for the json data can be either string / int which is causing problems when UnMarshalling
type OddsMarket struct { type OddsMarket struct {
ID ValidInt64 `json:"id"` ID StringOrNumber `json:"id"`
Name string `json:"name"` Name string `json:"name"`
Odds []json.RawMessage `json:"odds"` Odds []json.RawMessage `json:"odds"`
Header string `json:"header,omitempty"` Header string `json:"header,omitempty"`

View File

@ -31,6 +31,7 @@ func (n *ValidInt64) UnmarshalJSON(data []byte) error {
} }
v, err := strconv.ParseInt(s, 10, 64) v, err := strconv.ParseInt(s, 10, 64)
if err != nil { if err != nil {
fmt.Printf("Failed to parse the value of %v \n\n", s)
return err return err
} }
n.Value, n.Valid = v, true n.Value, n.Valid = v, true
@ -42,7 +43,7 @@ func (n *ValidInt64) UnmarshalJSON(data []byte) error {
n.Value, n.Valid = v, true n.Value, n.Valid = v, true
return nil return nil
} }
fmt.Printf("Failed to parse the value of %v", s)
return fmt.Errorf("invalid int64 value: %s", string(data)) return fmt.Errorf("invalid int64 value: %s", string(data))
} }

View File

@ -12,6 +12,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/SamuelTariku/FortuneBet-Backend/internal/config"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/repository" "github.com/SamuelTariku/FortuneBet-Backend/internal/repository"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/settings" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/settings"
@ -25,14 +26,16 @@ type service struct {
store *repository.Store store *repository.Store
settingSvc settings.Service settingSvc settings.Service
mongoLogger *zap.Logger mongoLogger *zap.Logger
cfg *config.Config
} }
func New(token string, store *repository.Store, settingSvc settings.Service, mongoLogger *zap.Logger) Service { func New(token string, store *repository.Store, settingSvc settings.Service, mongoLogger *zap.Logger, cfg *config.Config) Service {
return &service{ return &service{
token: token, token: token,
store: store, store: store,
settingSvc: settingSvc, settingSvc: settingSvc,
mongoLogger: mongoLogger, mongoLogger: mongoLogger,
cfg: cfg,
} }
} }
@ -217,10 +220,18 @@ func (s *service) fetchUpcomingEventsFromProvider(ctx context.Context, source_ur
s.mongoLogger.Error("Failed to fetch event data for page", zap.Error(err)) s.mongoLogger.Error("Failed to fetch event data for page", zap.Error(err))
return return
} }
const pageLimit int = 200
sportIDs := []int{1, 18, 17, 3, 83, 15, 12, 19, 8, 16, 91} var pageLimit int
// const pageLimit int = 1 var sportIDs []int
// sportIDs := []int{1}
// Restricting the page to 1 on development, which drastically reduces the amount of events that is fetched
if s.cfg.Env == "development" {
pageLimit = 1
sportIDs = []int{1}
} else {
pageLimit = 200
sportIDs = []int{1, 18, 17, 3, 83, 15, 12, 19, 8, 16, 91}
}
var skippedLeague []string var skippedLeague []string
var totalEvents = 0 var totalEvents = 0

View File

@ -88,67 +88,49 @@ func (s *ServiceImpl) fetchBet365Odds(ctx context.Context) error {
return err return err
} }
var errs []error
for index, event := range eventIDs { for index, event := range eventIDs {
if s.config.Env == "development" {
log.Printf("📡 Fetching prematch odds for event ID: %v (%d/%d) ", event.ID, index, len(eventIDs)) log.Printf("📡 Fetching prematch odds for event ID: %v (%d/%d) ", event.ID, index, len(eventIDs))
}
eventLogger := s.mongoLogger.With(
zap.String("eventID", event.ID),
zap.Int32("sportID", event.SportID),
)
oddsData, err := s.FetchNonLiveOddsByEventID(ctx, event.ID) oddsData, err := s.FetchNonLiveOddsByEventID(ctx, event.ID)
if err != nil || oddsData.Success != 1 { if err != nil || oddsData.Success != 1 {
s.mongoLogger.Error( eventLogger.Error("Failed to fetch prematch odds", zap.Error(err))
"Failed to fetch prematch odds",
zap.String("eventID", event.ID),
zap.Error(err),
)
errs = append(errs, fmt.Errorf("failed to fetch prematch odds for event %v: %w", event.ID, err))
continue continue
} }
parsedOddSections, err := s.ParseOddSections(ctx, oddsData.Results[0], event.SportID) parsedOddSections, err := s.ParseOddSections(ctx, oddsData.Results[0], event.SportID)
if err != nil { if err != nil {
s.mongoLogger.Error( eventLogger.Error("Failed to parse odd section", zap.Error(err))
"Failed to parse odd section",
zap.String("eventID", event.ID),
zap.Int32("sportID", event.SportID),
zap.Error(err),
)
errs = append(errs, fmt.Errorf("failed to parse odd section for event %v: %w", event.ID, err))
continue continue
} }
parsedOddLogger := eventLogger.With(
zap.String("parsedOddSectionFI", parsedOddSections.EventFI),
zap.Int("main_sections_count", len(parsedOddSections.Sections)),
zap.Int("other_sections_count", len(parsedOddSections.OtherRes)),
)
if parsedOddSections.EventFI == "" { if parsedOddSections.EventFI == "" {
s.mongoLogger.Error( parsedOddLogger.Error("Skipping result with no valid Event FI field", zap.Error(err))
"Skipping result with no valid Event FI field",
zap.String("FI", parsedOddSections.EventFI),
zap.String("eventID", event.ID),
zap.Int32("sportID", event.SportID),
zap.Error(err),
)
errs = append(errs, errors.New("event FI is empty"))
continue continue
} }
if len(parsedOddSections.Sections) == 0 {
parsedOddLogger.Warn("Event has no odds in main sections", zap.Error(err))
}
for oddCategory, section := range parsedOddSections.Sections { for oddCategory, section := range parsedOddSections.Sections {
if err := s.storeSection(ctx, event.ID, parsedOddSections.EventFI, oddCategory, section); err != nil { if err := s.storeSection(ctx, event.ID, parsedOddSections.EventFI, oddCategory, section); err != nil {
s.mongoLogger.Error( parsedOddLogger.Error("Error storing odd section", zap.String("odd", oddCategory), zap.Error(err))
"Error storing odd section",
zap.String("eventID", event.ID),
zap.String("odd", oddCategory),
zap.Int32("sportID", event.SportID),
zap.Error(err),
)
errs = append(errs, err)
} }
} }
for _, section := range parsedOddSections.OtherRes { for _, section := range parsedOddSections.OtherRes {
if err := s.storeSection(ctx, event.ID, parsedOddSections.EventFI, "others", section); err != nil { if err := s.storeSection(ctx, event.ID, parsedOddSections.EventFI, "others", section); err != nil {
s.mongoLogger.Error( parsedOddLogger.Error("Error storing odd other section", zap.Error(err))
"Error storing odd other section",
zap.String("eventID", event.ID),
zap.Int32("sportID", event.SportID),
zap.Error(err),
)
errs = append(errs, err)
continue continue
} }
} }
@ -157,10 +139,6 @@ func (s *ServiceImpl) fetchBet365Odds(ctx context.Context) error {
} }
for err := range errs {
log.Printf("❌ Error: %v", err)
}
return nil return nil
} }
@ -345,6 +323,7 @@ func (s *ServiceImpl) ParseOddSections(ctx context.Context, res json.RawMessage,
if err := json.Unmarshal(res, &footballRes); err != nil { if err := json.Unmarshal(res, &footballRes); err != nil {
s.mongoLogger.Error( s.mongoLogger.Error(
"Failed to unmarshal football result", "Failed to unmarshal football result",
zap.Error(err), zap.Error(err),
) )
return domain.ParseOddSectionsRes{}, err return domain.ParseOddSectionsRes{}, err
@ -534,6 +513,10 @@ func (s *ServiceImpl) ParseOddSections(ctx context.Context, res json.RawMessage,
func (s *ServiceImpl) storeSection(ctx context.Context, eventID, fi, sectionName string, section domain.OddsSection) error { func (s *ServiceImpl) storeSection(ctx context.Context, eventID, fi, sectionName string, section domain.OddsSection) error {
if len(section.Sp) == 0 { if len(section.Sp) == 0 {
s.mongoLogger.Warn("Event Section is empty",
zap.String("eventID", eventID),
zap.String("sectionName", sectionName),
)
return nil return nil
} }
@ -542,41 +525,36 @@ func (s *ServiceImpl) storeSection(ctx context.Context, eventID, fi, sectionName
var errs []error var errs []error
for marketType, market := range section.Sp { for marketType, market := range section.Sp {
marketLogger := s.mongoLogger.With(
zap.String("eventID", eventID),
zap.String("sectionName", sectionName),
zap.String("market_id", string(market.ID)),
zap.String("marketType", marketType),
zap.String("marketName", market.Name),
)
if len(market.Odds) == 0 { if len(market.Odds) == 0 {
// marketLogger.Warn("Skipping market with no odds")
continue continue
} }
// Check if the market id is a string marketIDint, err := strconv.ParseInt(string(market.ID), 10, 64)
marketIDint := market.ID.Value if err != nil {
// if err != nil { marketLogger.Warn("skipping market section where market_id is not int")
// s.mongoLogger.Error( continue
// "Invalid market id", }
// zap.Int64("market_id", marketIDint),
// zap.String("market_name", market.Name),
// zap.String("eventID", eventID),
// zap.Error(err),
// )
// continue
// }
marketIDstr := strconv.FormatInt(marketIDint, 10) marketIDstr := strconv.FormatInt(marketIDint, 10)
isSupported, ok := domain.SupportedMarkets[marketIDint] isSupported, ok := domain.SupportedMarkets[marketIDint]
if !ok || !isSupported { if !ok || !isSupported {
// s.logger.Info("Unsupported market_id", "marketID", marketIDint, "marketName", market.Name) // marketLogger.Warn("skipping market that isn't supported", zap.Bool("is_market_found", ok))
continue continue
} }
marketOdds, err := convertRawMessage(market.Odds) marketOdds, err := convertRawMessage(market.Odds)
if err != nil { if err != nil {
s.mongoLogger.Error( marketLogger.Error("failed to convert market.Odds to json.RawMessage to []map[string]interface{}", zap.Error(err))
"failed to convert market.Odds to json.RawMessage to []map[string]interface{}",
zap.String("market_id", marketIDstr),
zap.String("market_name", market.Name),
zap.String("eventID", eventID),
zap.Error(err),
)
errs = append(errs, err) errs = append(errs, err)
continue continue
} }
@ -593,25 +571,13 @@ func (s *ServiceImpl) storeSection(ctx context.Context, eventID, fi, sectionName
} }
if err := s.CheckAndInsertOddHistory(ctx, marketRecord); err != nil { if err := s.CheckAndInsertOddHistory(ctx, marketRecord); err != nil {
s.mongoLogger.Error( marketLogger.Error("failed to check and insert odd history", zap.Error(err))
"failed to check and insert odd history",
zap.String("market_id", marketIDstr),
zap.String("market_name", market.Name),
zap.String("eventID", eventID),
zap.Error(err),
)
continue continue
} }
err = s.store.SaveOddMarket(ctx, marketRecord) err = s.store.SaveOddMarket(ctx, marketRecord)
if err != nil { if err != nil {
s.mongoLogger.Error( marketLogger.Error("failed to save market", zap.Error(err))
"failed to save market",
zap.String("market_id", marketIDstr),
zap.String("market_name", market.Name),
zap.String("eventID", eventID),
zap.Error(err),
)
errs = append(errs, fmt.Errorf("market %v: %w", market.ID, err)) errs = append(errs, fmt.Errorf("market %v: %w", market.ID, err))
continue continue
} }

View File

@ -1007,17 +1007,17 @@ func (s *Service) GetResultsForEvent(ctx context.Context, eventID string) (json.
outcomes := make([]domain.BetOutcome, 0) outcomes := make([]domain.BetOutcome, 0)
for _, section := range parsedOddSections.Sections { for _, section := range parsedOddSections.Sections {
for _, market := range section.Sp { for _, market := range section.Sp {
marketIDint := market.ID.Value marketIDint, err := strconv.ParseInt(string(market.ID), 10, 64)
// if err != nil { if err != nil {
// s.mongoLogger.Error( s.mongoLogger.Warn(
// "Invalid market id", "Invalid market id",
// zap.Int64("market_id", marketIDint), zap.Int64("market_id", marketIDint),
// zap.String("market_name", market.Name), zap.String("market_name", market.Name),
// zap.String("eventID", eventID), zap.String("eventID", eventID),
// zap.Error(err), zap.Error(err),
// ) )
// continue continue
// } }
isSupported, ok := domain.SupportedMarkets[marketIDint] isSupported, ok := domain.SupportedMarkets[marketIDint]