auto refresh
This commit is contained in:
@@ -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数据
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user