fix(小宝预警): 增加快照节流和 AI cooldown
This commit is contained in:
@@ -22,6 +22,10 @@ export interface RiskTrendSummary {
|
||||
pattern: 'continuous_rising' | 'continuous_falling' | 'score_delta' | 'stable' | 'unknown';
|
||||
}
|
||||
|
||||
const SNAPSHOT_SAVE_THROTTLE_MS = 10 * 60 * 1000;
|
||||
const SNAPSHOT_SCORE_DELTA = 5;
|
||||
const ONE_DAY_MS = 86_400_000;
|
||||
|
||||
export function summarizeRiskTrend(snapshots: XiaobaoRiskSnapshot[]): RiskTrendSummary {
|
||||
const sorted = [...snapshots].sort((a, b) => getSnapshotTime(a) - getSnapshotTime(b));
|
||||
if (sorted.length < 2) {
|
||||
@@ -85,6 +89,49 @@ export function buildRiskSignature(snapshot: XiaobaoRiskSnapshot): string {
|
||||
].join('|');
|
||||
}
|
||||
|
||||
export function findLatestDailySnapshot(
|
||||
snapshots: XiaobaoRiskSnapshot[],
|
||||
versionId: string,
|
||||
date: string,
|
||||
): XiaobaoRiskSnapshot | undefined {
|
||||
return snapshots
|
||||
.filter((snapshot) => snapshot.versionId === versionId && snapshot.date === date)
|
||||
.sort((a, b) => getSnapshotTime(b) - getSnapshotTime(a))[0];
|
||||
}
|
||||
|
||||
export function shouldSaveRiskSnapshot(
|
||||
current: XiaobaoRiskSnapshot,
|
||||
previous?: XiaobaoRiskSnapshot,
|
||||
now: Date = new Date(),
|
||||
): boolean {
|
||||
if (!previous) return true;
|
||||
if (previous.versionId !== current.versionId || previous.date !== current.date) return true;
|
||||
if (buildRiskSignature(current) === buildRiskSignature(previous)) return false;
|
||||
if (hasMaterialSnapshotChange(current, previous)) return true;
|
||||
|
||||
const previousTime = getSnapshotTime(previous);
|
||||
const nowTime = now.getTime();
|
||||
if (!Number.isFinite(previousTime) || !Number.isFinite(nowTime)) return true;
|
||||
return nowTime - previousTime >= SNAPSHOT_SAVE_THROTTLE_MS;
|
||||
}
|
||||
|
||||
function hasMaterialSnapshotChange(current: XiaobaoRiskSnapshot, previous: XiaobaoRiskSnapshot): boolean {
|
||||
if (current.riskLevel !== previous.riskLevel) return true;
|
||||
if (Math.abs(clampScore(current.riskScore) - clampScore(previous.riskScore)) >= SNAPSHOT_SCORE_DELTA) return true;
|
||||
if ((current.criticalBugCount ?? 0) !== (previous.criticalBugCount ?? 0)) return true;
|
||||
if (current.failedTestCount !== previous.failedTestCount) return true;
|
||||
if (current.blockedCount !== previous.blockedCount) return true;
|
||||
if (current.silentRiskCount !== previous.silentRiskCount) return true;
|
||||
return hasForecastShiftedByOneDay(current.forecastReleaseDate, previous.forecastReleaseDate);
|
||||
}
|
||||
|
||||
function hasForecastShiftedByOneDay(current?: string, previous?: string): boolean {
|
||||
if (!current && !previous) return false;
|
||||
if (!current || !previous) return true;
|
||||
const delta = Math.abs(new Date(current).getTime() - new Date(previous).getTime());
|
||||
return Number.isFinite(delta) && delta >= ONE_DAY_MS;
|
||||
}
|
||||
|
||||
function getSnapshotTime(snapshot: XiaobaoRiskSnapshot): number {
|
||||
const date = new Date(snapshot.createdAt || snapshot.date).getTime();
|
||||
return Number.isFinite(date) ? date : 0;
|
||||
|
||||
Reference in New Issue
Block a user