auto refresh

This commit is contained in:
2025-04-17 18:28:08 +08:00
parent 6025641ab1
commit 53e1611670
4 changed files with 820 additions and 26 deletions

View File

@@ -3,7 +3,17 @@
// 创建日期: 2023-11-21
import { Pool } from "https://deno.land/x/postgres@v0.17.0/mod.ts";
import { getResource, getVariable } from "https://deno.land/x/windmill@v1.183.0/mod.ts";
import { getResource, getVariable, setVariable } from "https://deno.land/x/windmill@v1.183.0/mod.ts";
// 同步状态接口
interface SyncState {
last_sync_time: string; // 上次同步的结束时间
records_synced: number; // 累计同步的记录数
last_run: string; // 上次运行的时间
}
// 同步状态键名
const SYNC_STATE_KEY = "f/shorturl_analytics/shorturl_to_clickhouse_state";
// PostgreSQL配置接口
interface PgConfig {
@@ -42,24 +52,15 @@ interface ShortUrlData {
* 同步PostgreSQL short_url.shorturl表数据到ClickHouse
*/
export async function main(
params: {
/** 同步数据的开始时间ISO 8601格式。默认为1小时前 */
start_time?: string;
/** 同步数据的结束时间ISO 8601格式。默认为当前时间 */
end_time?: string;
/** 是否为测试模式(不执行实际更新) */
dry_run?: boolean;
/** 是否显示详细日志 */
verbose?: boolean;
}
/** 是否为测试模式(不执行实际更新) */
dry_run = false,
/** 是否显示详细日志 */
verbose = false,
/** 是否重置同步状态(从头开始同步) */
reset_sync_state = false,
/** 如果没有同步状态往前查询多少小时的数据默认1小时 */
default_hours_back = 1
) {
// 设置默认参数
const oneHourAgo = new Date(Date.now() - 60 * 60 * 1000).toISOString();
const start_time = params.start_time || oneHourAgo;
const end_time = params.end_time || new Date().toISOString();
const dry_run = params.dry_run || false;
const verbose = params.verbose || false;
// 初始化日志函数
const log = (message: string, isVerbose = false) => {
if (!isVerbose || verbose) {
@@ -67,6 +68,33 @@ export async function main(
}
};
// 获取同步状态
let syncState: SyncState | null = null;
if (!reset_sync_state) {
try {
log("获取同步状态...", true);
const rawState = await getVariable(SYNC_STATE_KEY);
if (rawState) {
if (typeof rawState === "string") {
syncState = JSON.parse(rawState);
} else {
syncState = rawState as SyncState;
}
log(`找到上次同步状态: 最后同步时间 ${syncState.last_sync_time}, 已同步记录数 ${syncState.records_synced}`, true);
}
} catch (error) {
log(`获取同步状态失败: ${error}, 将使用默认设置`, true);
}
} else {
log("重置同步状态,从头开始同步", true);
}
// 设置时间范围
const oneHourAgo = new Date(Date.now() - default_hours_back * 60 * 60 * 1000).toISOString();
// 如果有同步状态,使用上次同步时间作为开始时间;否则使用默认时间
const start_time = syncState ? syncState.last_sync_time : oneHourAgo;
const end_time = new Date().toISOString();
log(`开始同步shorturl表数据: ${start_time}${end_time}`);
let pgPool: Pool | null = null;
@@ -90,6 +118,10 @@ export async function main(
log(`成功获取 ${shorturlData.length} 条shorturl数据`);
if (shorturlData.length === 0) {
// 更新同步状态,即使没有新数据
if (!dry_run) {
await updateSyncState(end_time, syncState ? syncState.records_synced : 0, log);
}
return { success: true, message: "没有找到需要更新的数据", updated: 0 };
}
@@ -100,10 +132,19 @@ export async function main(
if (!dry_run) {
const shorturlUpdated = await updateClickHouseShortUrl(shorturlData, chConfig, log);
// 更新同步状态
const totalSynced = (syncState ? syncState.records_synced : 0) + shorturlUpdated;
await updateSyncState(end_time, totalSynced, log);
return {
success: true,
message: "shorturl表数据同步完成",
shorturl_updated: shorturlUpdated
shorturl_updated: shorturlUpdated,
total_synced: totalSynced,
sync_state: {
last_sync_time: end_time,
records_synced: totalSynced
}
};
} else {
log("测试模式: 不执行实际更新");
@@ -129,6 +170,25 @@ export async function main(
}
}
/**
* 更新同步状态
*/
async function updateSyncState(lastSyncTime: string, recordsSynced: number, log: (message: string, isVerbose?: boolean) => void): Promise<void> {
try {
const newState: SyncState = {
last_sync_time: lastSyncTime,
records_synced: recordsSynced,
last_run: new Date().toISOString()
};
await setVariable(SYNC_STATE_KEY, newState);
log(`同步状态已更新: 最后同步时间 ${lastSyncTime}, 累计同步记录数 ${recordsSynced}`, true);
} catch (error) {
log(`更新同步状态失败: ${error}`, true);
// 继续执行,不中断同步过程
}
}
/**
* 从PostgreSQL获取shorturl数据
*/