From 9e4b0d994269ee9e0dca089f83086fc5a5c39e50 Mon Sep 17 00:00:00 2001 From: Samuel Tariku Date: Tue, 29 Apr 2025 10:35:39 +0300 Subject: [PATCH] limiting the crons because of the request limit --- db/migrations/000003_referal.up.sql | 6 +- db/query/events.sql | 25 +++++++- gen/db/events.sql.go | 80 ++++++++++++++++++++++++ internal/repository/event.go | 50 +++++++++++---- internal/services/event/port.go | 1 + internal/services/event/service.go | 6 +- internal/web_server/cron.go | 58 +++++++++-------- internal/web_server/handlers/prematch.go | 6 +- 8 files changed, 185 insertions(+), 47 deletions(-) diff --git a/db/migrations/000003_referal.up.sql b/db/migrations/000003_referal.up.sql index 12a8c2d..521e3e3 100644 --- a/db/migrations/000003_referal.up.sql +++ b/db/migrations/000003_referal.up.sql @@ -19,8 +19,8 @@ CREATE TABLE IF NOT EXISTS referral_settings ( CREATE TABLE IF NOT EXISTS referrals ( id BIGSERIAL PRIMARY KEY, referral_code VARCHAR(10) NOT NULL UNIQUE, - -- referrer_id VARCHAR(255) NOT NULL, - -- referred_id VARCHAR(255) UNIQUE, + referrer_id VARCHAR(255) NOT NULL, + referred_id VARCHAR(255) UNIQUE, status ReferralStatus NOT NULL DEFAULT 'PENDING', reward_amount DECIMAL(15, 2) NOT NULL DEFAULT 0.00, cashback_amount DECIMAL(15, 2) NOT NULL DEFAULT 0.00, @@ -33,7 +33,7 @@ CREATE TABLE IF NOT EXISTS referrals ( CONSTRAINT cashback_amount_positive CHECK (cashback_amount >= 0) ); CREATE INDEX idx_referrals_referral_code ON referrals (referral_code); --- CREATE INDEX idx_referrals_referrer_id ON referrals (referrer_id); +CREATE INDEX idx_referrals_referrer_id ON referrals (referrer_id); CREATE INDEX idx_referrals_status ON referrals (status); ALTER TABLE users ADD COLUMN IF NOT EXISTS referral_code VARCHAR(10) UNIQUE, diff --git a/db/query/events.sql b/db/query/events.sql index c9fbd1c..09ecdf5 100644 --- a/db/query/events.sql +++ b/db/query/events.sql @@ -140,6 +140,28 @@ FROM events WHERE is_live = false AND status = 'upcoming' ORDER BY start_time ASC; +-- name: GetExpiredUpcomingEvents :many +SELECT id, + sport_id, + match_name, + home_team, + away_team, + home_team_id, + away_team_id, + home_kit_image, + away_kit_image, + league_id, + league_name, + league_cc, + start_time, + is_live, + status, + fetched_at +FROM events +WHERE is_live = false + AND status = 'upcoming' + AND start_time < now() +ORDER BY start_time ASC; -- name: GetTotalEvents :one SELECT COUNT(*) FROM events @@ -205,10 +227,9 @@ WHERE id = $1 AND is_live = false AND status = 'upcoming' LIMIT 1; - -- name: UpdateMatchResult :exec UPDATE events SET score = $1, status = $2, fetched_at = NOW() -WHERE id = $3; +WHERE id = $3; \ No newline at end of file diff --git a/gen/db/events.sql.go b/gen/db/events.sql.go index d556187..ed9dedf 100644 --- a/gen/db/events.sql.go +++ b/gen/db/events.sql.go @@ -90,6 +90,86 @@ func (q *Queries) GetAllUpcomingEvents(ctx context.Context) ([]GetAllUpcomingEve return items, nil } +const GetExpiredUpcomingEvents = `-- name: GetExpiredUpcomingEvents :many +SELECT id, + sport_id, + match_name, + home_team, + away_team, + home_team_id, + away_team_id, + home_kit_image, + away_kit_image, + league_id, + league_name, + league_cc, + start_time, + is_live, + status, + fetched_at +FROM events +WHERE is_live = false + AND status = 'upcoming' + AND start_time < now() +ORDER BY start_time ASC +` + +type GetExpiredUpcomingEventsRow struct { + ID string `json:"id"` + SportID pgtype.Text `json:"sport_id"` + MatchName pgtype.Text `json:"match_name"` + HomeTeam pgtype.Text `json:"home_team"` + AwayTeam pgtype.Text `json:"away_team"` + HomeTeamID pgtype.Text `json:"home_team_id"` + AwayTeamID pgtype.Text `json:"away_team_id"` + HomeKitImage pgtype.Text `json:"home_kit_image"` + AwayKitImage pgtype.Text `json:"away_kit_image"` + LeagueID pgtype.Text `json:"league_id"` + LeagueName pgtype.Text `json:"league_name"` + LeagueCc pgtype.Text `json:"league_cc"` + StartTime pgtype.Timestamp `json:"start_time"` + IsLive pgtype.Bool `json:"is_live"` + Status pgtype.Text `json:"status"` + FetchedAt pgtype.Timestamp `json:"fetched_at"` +} + +func (q *Queries) GetExpiredUpcomingEvents(ctx context.Context) ([]GetExpiredUpcomingEventsRow, error) { + rows, err := q.db.Query(ctx, GetExpiredUpcomingEvents) + if err != nil { + return nil, err + } + defer rows.Close() + var items []GetExpiredUpcomingEventsRow + for rows.Next() { + var i GetExpiredUpcomingEventsRow + if err := rows.Scan( + &i.ID, + &i.SportID, + &i.MatchName, + &i.HomeTeam, + &i.AwayTeam, + &i.HomeTeamID, + &i.AwayTeamID, + &i.HomeKitImage, + &i.AwayKitImage, + &i.LeagueID, + &i.LeagueName, + &i.LeagueCc, + &i.StartTime, + &i.IsLive, + &i.Status, + &i.FetchedAt, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + const GetPaginatedUpcomingEvents = `-- name: GetPaginatedUpcomingEvents :many SELECT id, sport_id, diff --git a/internal/repository/event.go b/internal/repository/event.go index 9dbc88a..2e2824a 100644 --- a/internal/repository/event.go +++ b/internal/repository/event.go @@ -89,6 +89,34 @@ func (s *Store) GetAllUpcomingEvents(ctx context.Context) ([]domain.UpcomingEven } return upcomingEvents, nil } + +func (s *Store) GetExpiredUpcomingEvents(ctx context.Context) ([]domain.UpcomingEvent, error) { + events, err := s.queries.GetExpiredUpcomingEvents(ctx) + if err != nil { + return nil, err + } + + upcomingEvents := make([]domain.UpcomingEvent, len(events)) + for i, e := range events { + upcomingEvents[i] = domain.UpcomingEvent{ + ID: e.ID, + SportID: e.SportID.String, + MatchName: e.MatchName.String, + HomeTeam: e.HomeTeam.String, + AwayTeam: e.AwayTeam.String, + HomeTeamID: e.HomeTeamID.String, + AwayTeamID: e.AwayTeamID.String, + HomeKitImage: e.HomeKitImage.String, + AwayKitImage: e.AwayKitImage.String, + LeagueID: e.LeagueID.String, + LeagueName: e.LeagueName.String, + LeagueCC: e.LeagueCc.String, + StartTime: e.StartTime.Time.UTC(), + } + } + return upcomingEvents, nil +} + func (s *Store) GetPaginatedUpcomingEvents(ctx context.Context, limit int32, offset int32, leagueID domain.ValidString, sportID domain.ValidString) ([]domain.UpcomingEvent, int64, error) { events, err := s.queries.GetPaginatedUpcomingEvents(ctx, dbgen.GetPaginatedUpcomingEventsParams{ LeagueID: pgtype.Text{ @@ -165,16 +193,16 @@ func (s *Store) GetUpcomingEventByID(ctx context.Context, ID string) (domain.Upc }, nil } func (s *Store) UpdateFinalScore(ctx context.Context, eventID, fullScore, status string) error { - params := dbgen.UpdateMatchResultParams{ - Score: pgtype.Text{String: fullScore, Valid: true}, - Status: pgtype.Text{String: status, Valid: true}, - ID: eventID, - } + params := dbgen.UpdateMatchResultParams{ + Score: pgtype.Text{String: fullScore, Valid: true}, + Status: pgtype.Text{String: status, Valid: true}, + ID: eventID, + } - err := s.queries.UpdateMatchResult(ctx, params) - if err != nil { - return fmt.Errorf("failed to update final score for event %s: %w", eventID, err) - } + err := s.queries.UpdateMatchResult(ctx, params) + if err != nil { + return fmt.Errorf("failed to update final score for event %s: %w", eventID, err) + } - return nil -} \ No newline at end of file + return nil +} diff --git a/internal/services/event/port.go b/internal/services/event/port.go index 0a60c6a..05fd33b 100644 --- a/internal/services/event/port.go +++ b/internal/services/event/port.go @@ -10,6 +10,7 @@ type Service interface { FetchLiveEvents(ctx context.Context) error FetchUpcomingEvents(ctx context.Context) error GetAllUpcomingEvents(ctx context.Context) ([]domain.UpcomingEvent, error) + GetExpiredUpcomingEvents(ctx context.Context) ([]domain.UpcomingEvent, error) GetPaginatedUpcomingEvents(ctx context.Context, limit int32, offset int32, leagueID domain.ValidString, sportID domain.ValidString) ([]domain.UpcomingEvent, int64, error) GetUpcomingEventByID(ctx context.Context, ID string) (domain.UpcomingEvent, error) // GetAndStoreMatchResult(ctx context.Context, eventID string) error diff --git a/internal/services/event/service.go b/internal/services/event/service.go index 5ac621c..00814b7 100644 --- a/internal/services/event/service.go +++ b/internal/services/event/service.go @@ -101,7 +101,7 @@ func (s *service) FetchUpcomingEvents(ctx context.Context) error { sportIDs := []int{1} var totalPages int = 1 var page int = 0 - var limit int = 5 + var limit int = 100 var count int = 0 for _, sportID := range sportIDs { for page != totalPages { @@ -199,6 +199,10 @@ func (s *service) GetAllUpcomingEvents(ctx context.Context) ([]domain.UpcomingEv return s.store.GetAllUpcomingEvents(ctx) } +func (s *service) GetExpiredUpcomingEvents(ctx context.Context) ([]domain.UpcomingEvent, error) { + return s.store.GetExpiredUpcomingEvents(ctx) +} + func (s *service) GetPaginatedUpcomingEvents(ctx context.Context, limit int32, offset int32, leagueID domain.ValidString, sportID domain.ValidString) ([]domain.UpcomingEvent, int64, error) { return s.store.GetPaginatedUpcomingEvents(ctx, limit, offset, leagueID, sportID) } diff --git a/internal/web_server/cron.go b/internal/web_server/cron.go index af66fe7..1cfbaee 100644 --- a/internal/web_server/cron.go +++ b/internal/web_server/cron.go @@ -1,6 +1,8 @@ package httpserver import ( + // "context" + "context" "log" @@ -34,34 +36,38 @@ func StartDataFetchingCrons(eventService eventsvc.Service, oddsService oddssvc.S // } // }, // }, - { - spec: "0 */15 * * * *", // Every 15 minutes - task: func() { - if err := oddsService.FetchNonLiveOdds(context.Background()); err != nil { - log.Printf("FetchNonLiveOdds error: %v", err) - } - }, - }, - { - spec: "0 */15 * * * *", - task: func() { - log.Println("Fetching results for upcoming events...") + // { + // // spec: "0 */15 * * * *", // Every 15 minutes + // spec: "0 0 * * * *", // TODO: Every hour because of the 3600 requests per hour limit + // task: func() { - upcomingEvents, err := eventService.GetAllUpcomingEvents(context.Background()) - if err != nil { - log.Printf("Failed to fetch upcoming events: %v", err) - return - } + // if err := oddsService.FetchNonLiveOdds(context.Background()); err != nil { + // log.Printf("FetchNonLiveOdds error: %v", err) + // } + // time.Sleep(2 * time.Second) //This will restrict the fetching to 1800 requests per hour - for _, event := range upcomingEvents { - if err := resultService.FetchAndStoreResult(context.Background(), event.ID); err != nil { - log.Printf(" Failed to fetch/store result for event %s: %v", event.ID, err) - } else { - log.Printf(" Successfully stored result for event %s", event.ID) - } - } - }, - }, + // }, + // }, + // { + // spec: "0 */15 * * * *", + // task: func() { + // log.Println("Fetching results for upcoming events...") + + // upcomingEvents, err := eventService.GetAllUpcomingEvents(context.Background()) + // if err != nil { + // log.Printf("Failed to fetch upcoming events: %v", err) + // return + // } + + // for _, event := range upcomingEvents { + // if err := resultService.FetchAndStoreResult(context.Background(), event.ID); err != nil { + // log.Printf(" Failed to fetch/store result for event %s: %v", event.ID, err) + // } else { + // log.Printf(" Successfully stored result for event %s", event.ID) + // } + // } + // }, + // }, } for _, job := range schedule { diff --git a/internal/web_server/handlers/prematch.go b/internal/web_server/handlers/prematch.go index 7e8d64d..e4790e8 100644 --- a/internal/web_server/handlers/prematch.go +++ b/internal/web_server/handlers/prematch.go @@ -1,7 +1,6 @@ package handlers import ( - "fmt" "strconv" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" @@ -103,7 +102,6 @@ func (h *Handler) GetRawOddsByMarketID(c *fiber.Ctx) error { // @Failure 500 {object} response.APIResponse // @Router /prematch/events [get] func (h *Handler) GetAllUpcomingEvents(c *fiber.Ctx) error { - page := c.QueryInt("page", 1) pageSize := c.QueryInt("page_size", 10) leagueIDQuery := c.Query("league_id") @@ -120,9 +118,9 @@ func (h *Handler) GetAllUpcomingEvents(c *fiber.Ctx) error { events, total, err := h.eventSvc.GetPaginatedUpcomingEvents(c.Context(), int32(pageSize), int32(page)-1, leagueID, sportID) - fmt.Printf("League ID: %v", leagueID) + // fmt.Printf("League ID: %v", leagueID) if err != nil { - h.logger.Error("getting error", err) + h.logger.Error("getting error", "error", err) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve all upcoming events", nil, nil) }