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)
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)
notificationRepo := repository.NewNotificationRepository(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
type OddsMarket struct {
ID ValidInt64 `json:"id"`
ID StringOrNumber `json:"id"`
Name string `json:"name"`
Odds []json.RawMessage `json:"odds"`
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)
if err != nil {
fmt.Printf("Failed to parse the value of %v \n\n", s)
return err
}
n.Value, n.Valid = v, true
@ -42,7 +43,7 @@ func (n *ValidInt64) UnmarshalJSON(data []byte) error {
n.Value, n.Valid = v, true
return nil
}
fmt.Printf("Failed to parse the value of %v", s)
return fmt.Errorf("invalid int64 value: %s", string(data))
}

View File

@ -12,6 +12,7 @@ import (
"sync"
"time"
"github.com/SamuelTariku/FortuneBet-Backend/internal/config"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/repository"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/settings"
@ -25,14 +26,16 @@ type service struct {
store *repository.Store
settingSvc settings.Service
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{
token: token,
store: store,
settingSvc: settingSvc,
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))
return
}
const pageLimit int = 200
sportIDs := []int{1, 18, 17, 3, 83, 15, 12, 19, 8, 16, 91}
// const pageLimit int = 1
// sportIDs := []int{1}
var pageLimit int
var sportIDs []int
// 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 totalEvents = 0

View File

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

View File

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