This commit is contained in:
2026-04-19 13:23:00 +03:00
parent e4c74025e5
commit 1346924387
25 changed files with 1639 additions and 1076 deletions
+31 -50
View File
@@ -24,6 +24,7 @@ import {
DbEventPayload,
DbMarketPayload,
} from "./feeder.types";
import { isMatchCompleted } from "../../common/utils/match-status.util";
interface ProcessDateOptions {
onlyCompletedMatches?: boolean;
@@ -113,51 +114,16 @@ export class FeederService {
};
}
private parseScoreValue(value: unknown): number | null {
if (value === null || value === undefined || value === "") return null;
const parsed = Number(value);
return Number.isFinite(parsed) ? parsed : null;
}
private isCompletedMatchSummary(match: MatchSummary): boolean {
if (match.statusBoxContent === "ERT") return false;
const normalizedState = String(match.state || "")
.trim()
.toLowerCase();
const normalizedStatus = String(match.status || "")
.trim()
.toLowerCase();
const normalizedSubstate = String(match.substate || "")
.trim()
.toLowerCase();
if (["postgame", "post"].includes(normalizedState)) return true;
if (
["played", "finished", "ft", "afterpenalties", "penalties"].includes(
normalizedStatus,
)
) {
return true;
}
if (
["postgame", "post", "played", "finished", "ft"].includes(
normalizedSubstate,
)
) {
return true;
}
const homeScore = this.parseScoreValue(
match.score?.home ?? match.homeScore,
);
const awayScore = this.parseScoreValue(
match.score?.away ?? match.awayScore,
);
return homeScore !== null && awayScore !== null;
return isMatchCompleted({
state: match.state,
status: match.status,
substate: match.substate,
statusBoxContent: match.statusBoxContent,
score: match.score,
scoreHome: match.homeScore,
scoreAway: match.awayScore,
});
}
async runPreviousDayCompletedMatchesScan(
@@ -957,15 +923,30 @@ export class FeederService {
*/
// ==========================================
if (saved && hasCriticalError) {
// Collect missing components
const missingParts: string[] = [];
if (!stats) missingParts.push("Stats");
const completedMatch = isMatchCompleted({
state: headerData?.matchStatus ?? matchSummary.state,
status: matchSummary.status,
substate: matchSummary.substate,
statusBoxContent: matchSummary.statusBoxContent,
scoreHome: headerData?.scoreHome ?? matchSummary.score?.home,
scoreAway: headerData?.scoreAway ?? matchSummary.score?.away,
});
const missingParts: string[] = [];
if (scope === "all" && completedMatch) {
if (sport === "football" && !stats) missingParts.push("Stats");
if (sport === "basketball" && !basketballTeamStats)
missingParts.push("BoxScore");
if (oddsArray.length === 0) missingParts.push("Odds");
if (officialsData.length === 0) missingParts.push("Officials");
}
if (saved && (hasCriticalError || missingParts.length > 0)) {
const reason = hasCriticalError
? "missing data after upstream errors"
: "incomplete completed-match payload";
this.logger.warn(
`[${matchId}] Saved with MISSING DATA (502). Missing: [${missingParts.join(", ")}]. Scheduled for retry.`,
`[${matchId}] Saved with ${reason}. Missing: [${missingParts.join(", ")}]. Scheduled for retry.`,
);
return { success: false, retryable: true };
}