|
|
@@ -4,12 +4,15 @@ import dayjs from "dayjs";
|
|
|
import doneRateService from "../../src/services/doneRateService"; // 导入 DoneRateService
|
|
|
import artService from "../../src/services/artService"; // 👈 导入 ArtService
|
|
|
import { clickhouseService } from "../../src/app"; // 导入 ClickhouseService 实例
|
|
|
-import mongoose from "mongoose"; // 导入 mongoose 用于处理 ObjectId
|
|
|
+import mongoose, { Connection } from "mongoose"; // 导入 mongoose 和 Connection 用于处理远程连接
|
|
|
import Art, { IArt } from "../../src/models/artModel"; // 👈 导入 Art 模型和 IArt 接口
|
|
|
|
|
|
// ClickHouse 表名
|
|
|
const CLICKHOUSE_EVENTS_TABLE = "events_raw"; // 确保与 ClickHouseService 中的表名一致
|
|
|
|
|
|
+// 远程数据库连接 URL
|
|
|
+const REMOTE_MONGO_URI = "mongodb://coloring:coloring123.@hk.jccytech.cn:7881/?authSource=admin";
|
|
|
+
|
|
|
/**
|
|
|
* ClickHouse 查询结果接口:每日每个作品的独立开始用户数
|
|
|
*/
|
|
|
@@ -29,7 +32,7 @@ interface ClickHouseDoneCountResult {
|
|
|
/**
|
|
|
* 每日统计昨天的作品完成率。
|
|
|
* 统计逻辑从 ClickHouse 中提取数据,得到每个作品的完成情况,并更新到 doneRateModel。
|
|
|
- * 随后,根据这些日统计数据,累加更新 Art 表的总统计字段。
|
|
|
+ * 随后,根据这些日统计数据,累加更新本地和远程的 Art 表的总统计字段。
|
|
|
* @returns Promise<string> - 返回统计结果的摘要信息。
|
|
|
*/
|
|
|
async function run(): Promise<string> {
|
|
|
@@ -43,6 +46,9 @@ async function run(): Promise<string> {
|
|
|
|
|
|
console.log(`[DoneRate Cron] Processing data for date: ${yesterdayYYYYMMDD}`);
|
|
|
|
|
|
+ let remoteConn: Connection | null = null;
|
|
|
+ let updatedRemoteArtworksCount = 0;
|
|
|
+
|
|
|
try {
|
|
|
// --- 1. 从 ClickHouse 中提取数据 ---
|
|
|
|
|
|
@@ -130,8 +136,14 @@ async function run(): Promise<string> {
|
|
|
|
|
|
console.log(`[DoneRate Cron] DoneRate model update completed. Total artworks processed: ${totalProcessedArtworks}. Created: ${createdRecordsCount}, Updated: ${updatedRecordsCount}.`);
|
|
|
|
|
|
- // --- 3. 获取昨天的所有 DoneRate 记录,并更新 Art 表的统计字段 ---
|
|
|
- let updatedArtworksCount = 0; // for Art model
|
|
|
+ // --- 3. 获取昨天的所有 DoneRate 记录,并更新本地和远程的 Art 表 ---
|
|
|
+
|
|
|
+ // 建立远程数据库连接和模型
|
|
|
+ remoteConn = await mongoose.createConnection(REMOTE_MONGO_URI);
|
|
|
+ const RemoteArt = remoteConn.model<IArt>("Art", Art.schema);
|
|
|
+ console.log(`[DoneRate Cron] Connected to remote database.`);
|
|
|
+
|
|
|
+ let updatedLocalArtworksCount = 0; // for Art model
|
|
|
const yesterdayDoneRates = await doneRateService.getDoneRatesByDate(yesterdayYYYYMMDD);
|
|
|
console.log(`[DoneRate Cron] Found ${yesterdayDoneRates.length} DoneRate records for yesterday to update Art table.`);
|
|
|
|
|
|
@@ -148,27 +160,45 @@ async function run(): Promise<string> {
|
|
|
// 重新计算总完成率
|
|
|
const newCompletionRate = newTotalStartCount > 0 ? (newTotalDoneCount / newTotalStartCount) * 100 : 0;
|
|
|
|
|
|
- // 更新 Art 文档
|
|
|
+ // **【新增】** 更新本地 Art 文档
|
|
|
await artService.updateArt(artworkId.toString(), {
|
|
|
totalStartCount: newTotalStartCount,
|
|
|
totalDoneCount: newTotalDoneCount,
|
|
|
completionRate: newCompletionRate,
|
|
|
});
|
|
|
- updatedArtworksCount++;
|
|
|
+ updatedLocalArtworksCount++;
|
|
|
+
|
|
|
+ // **【新增】** 同步更新远程 Art 文档
|
|
|
+ const remoteArtDoc = await RemoteArt.findById(artworkId);
|
|
|
+ if (remoteArtDoc) {
|
|
|
+ remoteArtDoc.totalStartCount = newTotalStartCount;
|
|
|
+ remoteArtDoc.totalDoneCount = newTotalDoneCount;
|
|
|
+ remoteArtDoc.completionRate = newCompletionRate;
|
|
|
+ await remoteArtDoc.save();
|
|
|
+ updatedRemoteArtworksCount++;
|
|
|
+ } else {
|
|
|
+ console.warn(`[DoneRate Cron] Remote Art document with ID ${artworkId} not found. Skipping remote update.`);
|
|
|
+ }
|
|
|
} else {
|
|
|
- console.warn(`[DoneRate Cron] Art document with ID ${artworkId} not found for DoneRate record (date: ${doneRateDoc.date}). Skipping Art update.`);
|
|
|
+ console.warn(`[DoneRate Cron] Local Art document with ID ${artworkId} not found for DoneRate record (date: ${doneRateDoc.date}). Skipping Art update.`);
|
|
|
}
|
|
|
} catch (artUpdateError) {
|
|
|
console.error(`[DoneRate Cron] Error updating Art document for artwork ID ${doneRateDoc.res}:`, artUpdateError);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- const summary = `[DoneRate Cron] Daily done-rate calculation for ${yesterdayYYYYMMDD} completed. Total DoneRate processed: ${totalProcessedArtworks}. Created DoneRate: ${createdRecordsCount}, Updated DoneRate: ${updatedRecordsCount}. Updated Art records: ${updatedArtworksCount}.`;
|
|
|
+ const summary = `[DoneRate Cron] Daily done-rate calculation for ${yesterdayYYYYMMDD} completed. Total DoneRate processed: ${totalProcessedArtworks}. Created DoneRate: ${createdRecordsCount}, Updated DoneRate: ${updatedRecordsCount}. Updated Local Art records: ${updatedLocalArtworksCount}. Updated Remote Art records: ${updatedRemoteArtworksCount}.`;
|
|
|
console.log(summary);
|
|
|
return summary;
|
|
|
} catch (error) {
|
|
|
console.error(`[DoneRate Cron] Error during done-rate calculation for ${yesterdayYYYYMMDD}:`, error);
|
|
|
throw new Error("Failed to calculate daily done-rates."); // 抛出错误以通知 cron 调度器
|
|
|
+ } finally {
|
|
|
+ // 确保在任何情况下都关闭远程连接
|
|
|
+ if (remoteConn) {
|
|
|
+ await remoteConn.close();
|
|
|
+ console.log("[DoneRate Cron] Disconnected from remote database.");
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|