diff --git a/tools/telemetry_retention.py b/tools/telemetry_retention.py index 2e13015..72cd8a3 100644 --- a/tools/telemetry_retention.py +++ b/tools/telemetry_retention.py @@ -118,19 +118,42 @@ def _build_parser() -> _Parser: def _validate(parser: _Parser, args: argparse.Namespace) -> None: - """校验参数组合;任何不合法组合以退出码 1 结束(P5: 不给默认值掩盖错误)。""" + """校验参数组合;任何不合法组合以退出码 1 结束(P5: 不给默认值掩盖错误)。 + + **校验链的顺序就是错误消息的优先级**: 先两端通用,再按 backend 分支——同时给出 + 多个错误参数时,报出的是链上最先命中的那条。 + """ + _validate_shared(parser, args) + if args.backend == "sqlite": + _validate_sqlite(parser, args) + return + _validate_postgres(parser, args) + + +def _validate_shared(parser: _Parser, args: argparse.Namespace) -> None: + """两端通用的校验。 + + `--vacuum` 与 `--apply` 的联动归在这里(而不是 SQLite 分支): 它是"别在只想看看的 + 时候重写整个库"这条安全约束,先于"这个参数属于哪个 backend"成立。 + """ if args.older_than_days < 0: parser.error("--older-than-days 必须 >= 0") if args.vacuum and not args.apply: parser.error("--vacuum 会重写整个库文件,必须与 --apply 同时给") - if args.backend == "sqlite": - if args.path is None: - parser.error("--backend sqlite 需要 --path") - if args.dsn is not None: - parser.error("--backend sqlite 不接受 --dsn") - if args.batch_size is not None: - parser.error("--batch-size 仅用于 --backend postgres") - return + + +def _validate_sqlite(parser: _Parser, args: argparse.Namespace) -> None: + """SQLite 分支: 必须有 --path,且拒绝一切 postgres 专属参数(不静默忽略)。""" + if args.path is None: + parser.error("--backend sqlite 需要 --path") + if args.dsn is not None: + parser.error("--backend sqlite 不接受 --dsn") + if args.batch_size is not None: + parser.error("--batch-size 仅用于 --backend postgres") + + +def _validate_postgres(parser: _Parser, args: argparse.Namespace) -> None: + """Postgres 分支: 必须有 --dsn,拒绝 sqlite 专属参数,并在此落 --batch-size 缺省值。""" if args.dsn is None: parser.error("--backend postgres 需要 --dsn") if args.path is not None: