|
|
@@ -18,6 +18,8 @@ from typing import Any
|
|
|
|
|
|
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
|
|
|
|
|
|
+from examples.demand.pg_pattern_repository import normalize_platform
|
|
|
+
|
|
|
|
|
|
def _load_project_env() -> None:
|
|
|
try:
|
|
|
@@ -66,7 +68,7 @@ def _build_scope(row: dict[str, Any], execution_id: int, count: int) -> dict[str
|
|
|
return {
|
|
|
"scope_source": "odps_gap",
|
|
|
"merge_leve2": row["cluster_name"],
|
|
|
- "platform": row.get("platform_type") or "piaoquan",
|
|
|
+ "platform": normalize_platform(row.get("platform_type") or "piaoquan"),
|
|
|
"gap_dt": row.get("gap_dt"),
|
|
|
"requested_count": int(count),
|
|
|
"lack_count": row.get("lack_count"),
|
|
|
@@ -85,6 +87,11 @@ def parse_args() -> argparse.Namespace:
|
|
|
parser.add_argument("--per-category-count", type=int, default=None, help="Override each selected gap row count")
|
|
|
parser.add_argument("--run-label-prefix", default=None, help="Prefix stored in ext_data.run_label")
|
|
|
parser.add_argument("--dry-run", action="store_true", help="Print gap plan only; do not call the agent")
|
|
|
+ parser.add_argument(
|
|
|
+ "--fail-on-partition-not-ready",
|
|
|
+ action="store_true",
|
|
|
+ help="Exit non-zero when yesterday's Hive source partition is not ready; useful for systemd retry.",
|
|
|
+ )
|
|
|
return parser.parse_args()
|
|
|
|
|
|
|
|
|
@@ -92,7 +99,10 @@ async def async_main() -> dict[str, Any]:
|
|
|
_load_project_env()
|
|
|
args = parse_args()
|
|
|
|
|
|
- from examples.demand.data_query_tools import get_demand_merge_level2_names
|
|
|
+ from examples.demand.data_query_tools import (
|
|
|
+ get_demand_gap_source_partition_status,
|
|
|
+ get_demand_merge_level2_names,
|
|
|
+ )
|
|
|
from examples.demand.db_manager import query_latest_success_execution_id
|
|
|
|
|
|
execution_id = args.execution_id or query_latest_success_execution_id()
|
|
|
@@ -100,7 +110,28 @@ async def async_main() -> dict[str, Any]:
|
|
|
raise ValueError("未找到 PG Pattern V2 success execution")
|
|
|
_validate_execution_success(int(execution_id))
|
|
|
|
|
|
- gap_rows = get_demand_merge_level2_names()
|
|
|
+ partition_status = get_demand_gap_source_partition_status()
|
|
|
+ if not partition_status.get("ready"):
|
|
|
+ return {
|
|
|
+ "execution_id": int(execution_id),
|
|
|
+ "dry_run": bool(args.dry_run),
|
|
|
+ "skipped_reason": "hive_gap_source_partition_not_ready",
|
|
|
+ "partition_status": partition_status,
|
|
|
+ "planned": [],
|
|
|
+ "results": [],
|
|
|
+ "_exit_code": 75 if args.fail_on_partition_not_ready else 0,
|
|
|
+ }
|
|
|
+
|
|
|
+ gap_rows = get_demand_merge_level2_names(day=str(partition_status["dt"]))
|
|
|
+ if not gap_rows:
|
|
|
+ return {
|
|
|
+ "execution_id": int(execution_id),
|
|
|
+ "dry_run": bool(args.dry_run),
|
|
|
+ "skipped_reason": "hive_gap_rows_empty",
|
|
|
+ "partition_status": partition_status,
|
|
|
+ "planned": [],
|
|
|
+ "results": [],
|
|
|
+ }
|
|
|
if args.skip_categories:
|
|
|
gap_rows = gap_rows[max(int(args.skip_categories), 0):]
|
|
|
if args.max_categories is not None:
|
|
|
@@ -154,6 +185,7 @@ async def async_main() -> dict[str, Any]:
|
|
|
return {
|
|
|
"execution_id": int(execution_id),
|
|
|
"dry_run": bool(args.dry_run),
|
|
|
+ "partition_status": partition_status,
|
|
|
"planned": planned,
|
|
|
"results": results,
|
|
|
}
|
|
|
@@ -161,7 +193,10 @@ async def async_main() -> dict[str, Any]:
|
|
|
|
|
|
def main() -> None:
|
|
|
result = asyncio.run(async_main())
|
|
|
+ exit_code = int(result.pop("_exit_code", 0) or 0)
|
|
|
print(json.dumps(result, ensure_ascii=False, indent=2))
|
|
|
+ if exit_code:
|
|
|
+ raise SystemExit(exit_code)
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|