|
|
@@ -7,21 +7,37 @@ const doneRateService_1 = __importDefault(require("../../src/services/doneRateSe
|
|
|
const clients_1 = require("../../src/services/clients");
|
|
|
const mongoose_1 = __importDefault(require("mongoose")); // 导入 mongoose 和 Connection 用于处理远程连接
|
|
|
const totalDoneRateModel_1 = __importDefault(require("../../src/models/totalDoneRateModel")); // 导入 TotalDoneRate 模型 (已包含 totalTipCount)
|
|
|
-const doneRateModel_1 = __importDefault(require("../../src/models/doneRateModel")); // 【新增】导入 DoneRateModel 用于聚合历史数据
|
|
|
+const doneRateModel_1 = __importDefault(require("../../src/models/doneRateModel")); // 导入 DoneRateModel 用于聚合历史数据
|
|
|
// ClickHouse 表名
|
|
|
const CLICKHOUSE_EVENTS_TABLE = "events"; // 确保与 ClickHouseService 中的表名一致
|
|
|
/**
|
|
|
- * 每日统计昨天的作品完成率。
|
|
|
- * 统计逻辑从 ClickHouse 中提取数据,得到每个作品的完成情况、道具使用情况,并更新到 DoneRate 模型。
|
|
|
- * 随后,根据这些日统计数据,通过聚合 TotalDoneRate 表 (包括 totalTipCount)。
|
|
|
+ * 每日统计作品完成率。
|
|
|
+ * 如果提供了 dateStr (YYYY-MM-DD 或 YYYYMMDD),则统计该日的数据;否则,默认统计昨天的数据。
|
|
|
+ * 统计逻辑从 ClickHouse 中提取数据,得到每个作品的完成情况、道具使用情况,并更新到 doneRateModel。
|
|
|
+ * 随后,通过聚合这些日统计数据,更新本地的 totalDoneRate 表 (包括 totalTipCount)。
|
|
|
+ * @param dateStr 可选参数,指定要统计的日期 (例如: '2023-10-25')。
|
|
|
* @returns Promise<string> - 返回统计结果的摘要信息。
|
|
|
*/
|
|
|
-async function run() {
|
|
|
- console.log("[DoneRate Cron] Starting daily done-rate calculation for yesterday...");
|
|
|
- // 获取昨天和今天的日期
|
|
|
- const yesterday = (0, dayjs_1.default)().subtract(1, "day");
|
|
|
+async function run(dateStr) {
|
|
|
+ console.log("[DoneRate Cron] Starting done-rate calculation...");
|
|
|
+ // --- 确定目标日期 ---
|
|
|
+ let targetDay;
|
|
|
+ if (dateStr) {
|
|
|
+ targetDay = (0, dayjs_1.default)(dateStr).startOf("day");
|
|
|
+ if (!targetDay.isValid()) {
|
|
|
+ throw new Error(`Invalid date format provided: ${dateStr}`);
|
|
|
+ }
|
|
|
+ console.log(`[DoneRate Cron] Running for specified date: ${targetDay.format("YYYY-MM-DD")}`);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ // 默认执行逻辑:统计昨天
|
|
|
+ targetDay = (0, dayjs_1.default)().subtract(1, "day").startOf("day");
|
|
|
+ console.log(`[DoneRate Cron] Running for default date (yesterday): ${targetDay.format("YYYY-MM-DD")}`);
|
|
|
+ }
|
|
|
+ // 使用 targetDay 变量名以兼容后续代码
|
|
|
+ const yesterday = targetDay;
|
|
|
const yesterdayYYYYMMDD = yesterday.format("YYYYMMDD");
|
|
|
- const yesterdayStart = yesterday.startOf("day").toDate();
|
|
|
+ const yesterdayStart = yesterday.toDate();
|
|
|
const yesterdayEnd = yesterday.endOf("day").toDate();
|
|
|
// 格式化日期字符串,使其符合 ClickHouse 的 toDateTime() 函数要求
|
|
|
const yesterdayStartString = (0, dayjs_1.default)(yesterdayStart).format("YYYY-MM-DD HH:mm:ss");
|
|
|
@@ -29,8 +45,7 @@ async function run() {
|
|
|
console.log(`[DoneRate Cron] Processing data for date: ${yesterdayYYYYMMDD}`);
|
|
|
try {
|
|
|
// --- 1. 从 ClickHouse 中提取数据 (Start, Done, Tip Counts) ---
|
|
|
- // (此处是 ClickHouse 可能发生超时的地方)
|
|
|
- // 1.1 查询昨天每个作品的独立开始用户数
|
|
|
+ // 1.1 查询目标日期每个作品的独立开始用户数
|
|
|
const startCountsQuery = `
|
|
|
SELECT
|
|
|
res,
|
|
|
@@ -53,7 +68,7 @@ async function run() {
|
|
|
}
|
|
|
});
|
|
|
console.log(`[DoneRate Cron] Retrieved ${startResults.length} unique start counts from ClickHouse.`);
|
|
|
- // 1.2 查询昨天每个作品的独立完成用户数
|
|
|
+ // 1.2 查询目标日期每个作品的独立完成用户数
|
|
|
const doneCountsQuery = `
|
|
|
SELECT
|
|
|
res,
|
|
|
@@ -76,7 +91,7 @@ async function run() {
|
|
|
}
|
|
|
});
|
|
|
console.log(`[DoneRate Cron] Retrieved ${doneResults.length} unique done counts from ClickHouse.`);
|
|
|
- // 1.3 查询昨天每个作品的使用道具数
|
|
|
+ // 1.3 查询目标日期每个作品的使用道具数
|
|
|
const tipCountsQuery = `
|
|
|
SELECT
|
|
|
res,
|
|
|
@@ -121,11 +136,10 @@ async function run() {
|
|
|
const totalProcessedArtworks = createdRecordsCount + updatedRecordsCount;
|
|
|
console.log(`[DoneRate Cron] DoneRate model (Daily) update completed. Total artworks processed: ${totalProcessedArtworks}. Created: ${createdRecordsCount}, Updated: ${updatedRecordsCount}.`);
|
|
|
// --- 3. 重新聚合并更新本地的 TotalDoneRate 表 (累计记录) ---
|
|
|
- // 🚨 修正:原先的 Read-Modify-Write 逻辑被替换为更健壮的 MongoDB 聚合。
|
|
|
// 通过聚合 DoneRate 日记录来计算最新的累计总数,确保幂等性。
|
|
|
- // 3.1 聚合所有历史 DoneRate 记录直到昨天
|
|
|
+ // 3.1 聚合所有历史 DoneRate 记录直到昨天 (即 targetDay)
|
|
|
const aggregationPipeline = [
|
|
|
- // 匹配所有小于或等于昨天的日期记录
|
|
|
+ // 匹配所有小于或等于目标日期的记录
|
|
|
{ $match: { date: { $lte: yesterdayYYYYMMDD } } },
|
|
|
{
|
|
|
$group: {
|
|
|
@@ -180,9 +194,15 @@ async function run() {
|
|
|
catch (error) {
|
|
|
console.error(`[DoneRate Cron] Error during done-rate calculation for ${yesterdayYYYYMMDD}:`, error);
|
|
|
// 重新抛出错误,以便 cron 调度器能够捕获并记录失败
|
|
|
- throw new Error(`Failed to calculate daily done-rates: ${error instanceof Error ? error.message : String(error)}`);
|
|
|
+ throw new Error(`Failed to calculate daily done-rates for ${yesterdayYYYYMMDD}: ${error instanceof Error ? error.message : String(error)}`);
|
|
|
}
|
|
|
finally {
|
|
|
}
|
|
|
}
|
|
|
+if (require.main === module) {
|
|
|
+ run().catch((err) => {
|
|
|
+ console.error(err);
|
|
|
+ process.exit(1);
|
|
|
+ });
|
|
|
+}
|
|
|
module.exports = { run };
|