Files
syncio/app/backfill_watermarks.py
brusnitsyn b5d1f61a82 v2026.06
2026-06-10 16:53:03 +09:00

89 lines
2.9 KiB
Python

import argparse
import json
import traceback
from .config import Config
def parse_args():
parser = argparse.ArgumentParser(
description="Backfill migration_state watermark-ами из MSSQL Life_ таблиц."
)
parser.add_argument(
"--tables",
nargs="+",
help="Список source_table/target_table для обработки. По умолчанию берутся все incremental-таблицы.",
)
parser.add_argument(
"--overwrite",
action="store_true",
help="Перезаписать уже существующие watermark в replicator.migration_state.",
)
parser.add_argument(
"--dry-run",
action="store_true",
help="Только показать, какие watermark будут записаны, без сохранения в PostgreSQL.",
)
parser.add_argument(
"--from-pg",
action="store_true",
help=(
"Определить watermark из уже реплицированных данных PostgreSQL: "
"для каждой таблицы загружает PK из PG и ищет соответствующие "
"x_DateTime/sequence в MSSQL Life_, не читая всю таблицу заново."
),
)
parser.add_argument(
"--json",
action="store_true",
help="Вывести итог в JSON.",
)
return parser.parse_args()
def main():
try:
from .migrator import DatabaseMigrator
args = parse_args()
config = Config()
migrator = DatabaseMigrator(config)
if args.from_pg:
summary = migrator.backfill_state_from_pg(
table_names=args.tables,
overwrite=args.overwrite,
dry_run=args.dry_run,
)
else:
summary = migrator.backfill_watermarks(
table_names=args.tables,
overwrite=args.overwrite,
dry_run=args.dry_run,
)
if args.json:
print(json.dumps(summary, ensure_ascii=False, indent=2, default=str))
else:
print("\n" + "=" * 60)
print("BACKFILL WATERMARKS ЗАВЕРШЕН")
print("=" * 60)
print(f"Обработано: {summary['processed']}")
print(f"Обновлено: {summary['updated']}")
print(f"Пропущено: {summary['skipped']}")
print(f"Ошибок: {summary['failed']}")
print("=" * 60)
return 1 if summary['failed'] > 0 else 0
except KeyboardInterrupt:
print("\nBackfill прерван пользователем")
return 130
except Exception as e:
print(f"Критическая ошибка: {e}")
print(traceback.format_exc())
return 1
if __name__ == "__main__":
raise SystemExit(main())