fix: incorrect time base when adjusting snapshot time

This commit is contained in:
alikia2x (寒寒) 2025-03-24 04:15:51 +08:00
parent 584a1be9f9
commit 0a73d28623
Signed by: alikia2x
GPG Key ID: 56209E0CCD8420C6

View File

@ -2,14 +2,14 @@ import { Client } from "https://deno.land/x/postgres@v0.19.3/mod.ts";
import { formatTimestampToPsql } from "lib/utils/formatTimestampToPostgre.ts"; import { formatTimestampToPsql } from "lib/utils/formatTimestampToPostgre.ts";
import { SnapshotScheduleType } from "./schema.d.ts"; import { SnapshotScheduleType } from "./schema.d.ts";
import logger from "lib/log/logger.ts"; import logger from "lib/log/logger.ts";
import { DAY, MINUTE } from "$std/datetime/constants.ts"; import { MINUTE } from "$std/datetime/constants.ts";
import { redis } from "lib/db/redis.ts"; import { redis } from "lib/db/redis.ts";
import { Redis } from "ioredis"; import { Redis } from "ioredis";
const WINDOW_SIZE = 2880; // 每天 2880 个 5 分钟窗口 const WINDOW_SIZE = 2880;
const REDIS_KEY = "cvsa:snapshot_window_counts"; // Redis Key 名称 const REDIS_KEY = "cvsa:snapshot_window_counts";
// 获取当前时间对应的窗口索引
function getCurrentWindowIndex(): number { function getCurrentWindowIndex(): number {
const now = new Date(); const now = new Date();
const minutesSinceMidnight = now.getHours() * 60 + now.getMinutes(); const minutesSinceMidnight = now.getHours() * 60 + now.getMinutes();
@ -17,7 +17,6 @@ function getCurrentWindowIndex(): number {
return currentWindow; return currentWindow;
} }
// 刷新内存数组
export async function refreshSnapshotWindowCounts(client: Client, redisClient: Redis) { export async function refreshSnapshotWindowCounts(client: Client, redisClient: Redis) {
const now = new Date(); const now = new Date();
const startTime = now.getTime(); const startTime = now.getTime();
@ -181,22 +180,24 @@ export async function adjustSnapshotTime(
const currentWindow = getCurrentWindowIndex(); const currentWindow = getCurrentWindowIndex();
// 计算目标窗口偏移量 // 计算目标窗口偏移量
const targetOffset = Math.floor((expectedStartTime.getTime() - Date.now()) / (5 * 60 * 1000)); const targetOffset = Math.floor((expectedStartTime.getTime() - Date.now()) / (5 * MINUTE));
// 在 Redis 中查找可用窗口 // 在 Redis 中查找可用窗口
for (let i = 0; i < WINDOW_SIZE; i++) { for (let i = 0; i < WINDOW_SIZE; i++) {
const offset = (currentWindow + targetOffset + i) % WINDOW_SIZE; const offset = (currentWindow + targetOffset + i) % WINDOW_SIZE;
const count = await getWindowCount(redisClient, offset); const count = await getWindowCount(redisClient, offset);
logger.debug(`offset: ${offset}, count: ${count}, expectedStartTime: ${expectedStartTime}`);
if (count < allowedCounts) { if (count < allowedCounts) {
// 找到可用窗口,更新计数 // 找到可用窗口,更新计数
await updateWindowCount(redisClient, offset, 1); await updateWindowCount(redisClient, offset, 1);
// 计算具体时间 // 计算具体时间
const windowStart = new Date(Date.now() + offset * 5 * 60 * 1000); const startPoint = new Date();
const randomDelay = Math.floor(Math.random() * 5 * 60 * 1000); startPoint.setHours(0, 0, 0, 0);
return new Date(windowStart.getTime() + randomDelay); const startTime = startPoint.getTime();
const windowStart = startTime + offset * 5 * MINUTE;
const randomDelay = Math.floor(Math.random() * 5 * MINUTE);
return new Date(windowStart + randomDelay);
} }
} }
@ -204,23 +205,6 @@ export async function adjustSnapshotTime(
return expectedStartTime; return expectedStartTime;
} }
export async function cleanupExpiredWindows(redisClient: Redis): Promise<void> {
const now = new Date();
const startTime = new Date(now.getTime() - 10 * DAY); // 保留最近 10 天的数据
// 获取所有窗口索引
const allOffsets = await redisClient.hkeys(REDIS_KEY);
// 删除过期窗口
for (const offsetStr of allOffsets) {
const offset = parseInt(offsetStr, 10);
const windowStart = new Date(startTime.getTime() + offset * 5 * MINUTE);
if (windowStart < startTime) {
await redisClient.hdel(REDIS_KEY, offsetStr);
}
}
}
export async function getSnapshotsInNextSecond(client: Client) { export async function getSnapshotsInNextSecond(client: Client) {
const query = ` const query = `