Add ntfy notification for full sync summary and enhance logging for success and failure results
This commit is contained in:
@@ -3,6 +3,7 @@ from config import SQL_SERVER_CONN, ACCESS_DRIVER, SYNC_MAPPING, BATCH_SIZE
|
|||||||
import db_utils
|
import db_utils
|
||||||
import time
|
import time
|
||||||
import os
|
import os
|
||||||
|
import ntfy_utils
|
||||||
from log_utils import (LoggerManager, log_success, log_error, log_warning, log_info, log_processing,
|
from log_utils import (LoggerManager, log_success, log_error, log_warning, log_info, log_processing,
|
||||||
log_skip, log_start, log_file, log_database, log_sync, log_complete)
|
log_skip, log_start, log_file, log_database, log_sync, log_complete)
|
||||||
|
|
||||||
@@ -30,6 +31,54 @@ def has_identity_column(sql_cursor, schema, table):
|
|||||||
sql_cursor.execute(query, (schema, table))
|
sql_cursor.execute(query, (schema, table))
|
||||||
return sql_cursor.fetchone()[0] > 0
|
return sql_cursor.fetchone()[0] > 0
|
||||||
|
|
||||||
|
def _send_summary_notification(sync_results, success_count, failed_count, total_rows, total_time):
|
||||||
|
"""发送汇总 ntfy 通知"""
|
||||||
|
if not sync_results:
|
||||||
|
return
|
||||||
|
|
||||||
|
# 分类成功和失败的表
|
||||||
|
success_tables = [r for r in sync_results if r['status'] == 'success']
|
||||||
|
failed_tables = [r for r in sync_results if r['status'] == 'failed']
|
||||||
|
|
||||||
|
# 构建消息
|
||||||
|
lines = []
|
||||||
|
lines.append("🎯 全量同步完成\n")
|
||||||
|
|
||||||
|
# 成功的表
|
||||||
|
if success_tables:
|
||||||
|
lines.append(f"✅ 成功 {len(success_tables)} 张表:")
|
||||||
|
for r in success_tables:
|
||||||
|
lines.append(f" • {r['table']}: {r['rows']:,} 行, {format_duration(r['duration'])}")
|
||||||
|
lines.append("")
|
||||||
|
|
||||||
|
# 失败的表
|
||||||
|
if failed_tables:
|
||||||
|
lines.append(f"❌ 失败 {failed_count} 张表:")
|
||||||
|
for r in failed_tables:
|
||||||
|
error_brief = r['error'][:50] + "..." if len(r['error']) > 50 else r['error']
|
||||||
|
lines.append(f" • {r['table']}: {error_brief}")
|
||||||
|
lines.append("")
|
||||||
|
|
||||||
|
# 总计
|
||||||
|
lines.append(f"总计: {total_rows:,} 行 | 用时: {format_duration(total_time)}")
|
||||||
|
|
||||||
|
message = "\n".join(lines)
|
||||||
|
|
||||||
|
# 根据成功/失败情况决定优先级和标签
|
||||||
|
if failed_count > 0:
|
||||||
|
priority = "high"
|
||||||
|
tags = ["warning", "database"]
|
||||||
|
else:
|
||||||
|
priority = "default"
|
||||||
|
tags = ["white_check_mark", "database"]
|
||||||
|
|
||||||
|
ntfy_utils.send_ntfy(
|
||||||
|
message=message,
|
||||||
|
title="全量同步完成",
|
||||||
|
priority=priority,
|
||||||
|
tags=tags
|
||||||
|
)
|
||||||
|
|
||||||
def run_full_sync():
|
def run_full_sync():
|
||||||
log_info("=" * 70)
|
log_info("=" * 70)
|
||||||
log_start( "全量初始化同步")
|
log_start( "全量初始化同步")
|
||||||
@@ -43,6 +92,9 @@ def run_full_sync():
|
|||||||
failed_tables = 0
|
failed_tables = 0
|
||||||
total_rows = 0
|
total_rows = 0
|
||||||
|
|
||||||
|
# 收集每张表的同步结果,用于最终汇总通知
|
||||||
|
sync_results = [] # 格式: {'table': str, 'status': 'success'|'failed', 'rows': int, 'duration': float, 'error': str}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
sql_conn = db_utils.get_sql_conn()
|
sql_conn = db_utils.get_sql_conn()
|
||||||
sql_cursor = sql_conn.cursor()
|
sql_cursor = sql_conn.cursor()
|
||||||
@@ -141,7 +193,16 @@ def run_full_sync():
|
|||||||
# 显示最终统计
|
# 显示最终统计
|
||||||
table_time = time.time() - table_start_time
|
table_time = time.time() - table_start_time
|
||||||
final_rate = table_rows / table_time if table_time > 0 else 0
|
final_rate = table_rows / table_time if table_time > 0 else 0
|
||||||
log_success( f"表 [{target_table}] 完成: {table_rows:,} 行 | 速率: {final_rate:,.0f} 行/秒 | 用时: {format_duration(table_time)}")
|
log_info( f"表 [{target_table}] 完成: {table_rows:,} 行 | 速率: {final_rate:,.0f} 行/秒 | 用时: {format_duration(table_time)}")
|
||||||
|
|
||||||
|
# 收集成功结果
|
||||||
|
sync_results.append({
|
||||||
|
'table': target_table,
|
||||||
|
'status': 'success',
|
||||||
|
'rows': table_rows,
|
||||||
|
'duration': table_time,
|
||||||
|
'error': None
|
||||||
|
})
|
||||||
|
|
||||||
success_tables += 1
|
success_tables += 1
|
||||||
file_success += 1
|
file_success += 1
|
||||||
@@ -151,7 +212,18 @@ def run_full_sync():
|
|||||||
except Exception as tbl_err:
|
except Exception as tbl_err:
|
||||||
failed_tables += 1
|
failed_tables += 1
|
||||||
file_failed += 1
|
file_failed += 1
|
||||||
log_error( f"表 [{acc_table}] 同步失败: {tbl_err}", exc_info=True)
|
error_msg = str(tbl_err)
|
||||||
|
log_info( f"表 [{acc_table}] 同步失败: {error_msg}")
|
||||||
|
|
||||||
|
# 收集失败结果
|
||||||
|
sync_results.append({
|
||||||
|
'table': target_table,
|
||||||
|
'status': 'failed',
|
||||||
|
'rows': 0,
|
||||||
|
'duration': time.time() - table_start_time,
|
||||||
|
'error': error_msg
|
||||||
|
})
|
||||||
|
|
||||||
sql_conn.rollback()
|
sql_conn.rollback()
|
||||||
|
|
||||||
# 确保清理 IDENTITY_INSERT 状态
|
# 确保清理 IDENTITY_INSERT 状态
|
||||||
@@ -179,7 +251,7 @@ def run_full_sync():
|
|||||||
# 总结统计
|
# 总结统计
|
||||||
sync_time = time.time() - sync_start_time
|
sync_time = time.time() - sync_start_time
|
||||||
log_info("\n" + "=" * 70)
|
log_info("\n" + "=" * 70)
|
||||||
log_complete( "全量同步任务结束")
|
log_info( "全量同步任务结束")
|
||||||
log_info("-" * 70)
|
log_info("-" * 70)
|
||||||
log_info( f"总表数: {total_tables} 张 | 成功: {success_tables} 张 | 失败: {failed_tables} 张")
|
log_info( f"总表数: {total_tables} 张 | 成功: {success_tables} 张 | 失败: {failed_tables} 张")
|
||||||
log_info( f"总行数: {total_rows:,} 行")
|
log_info( f"总行数: {total_rows:,} 行")
|
||||||
@@ -188,5 +260,8 @@ def run_full_sync():
|
|||||||
log_info( f"整体平均速率: {total_rows/sync_time:,.0f} 行/秒")
|
log_info( f"整体平均速率: {total_rows/sync_time:,.0f} 行/秒")
|
||||||
log_info("=" * 70)
|
log_info("=" * 70)
|
||||||
|
|
||||||
|
# 发送汇总 ntfy 通知
|
||||||
|
_send_summary_notification(sync_results, success_tables, failed_tables, total_rows, sync_time)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
run_full_sync()
|
run_full_sync()
|
||||||
Reference in New Issue
Block a user