step_cli.py 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. from __future__ import annotations
  2. import argparse
  3. import json
  4. import logging
  5. from pathlib import Path
  6. from typing import Any
  7. from supply_infra.db.repositories.pipeline_run_repo import PipelineRunRepository
  8. from supply_infra.db.repositories.pipeline_step_run_repo import PipelineStepRunRepository
  9. from supply_infra.db.session import dispose_engine, get_session
  10. from supply_infra.pipeline.contracts import StepContext
  11. from supply_infra.pipeline.registry import execute_registered_step
  12. logger = logging.getLogger(__name__)
  13. def execute_step_run(step_run_id: str) -> dict[str, Any]:
  14. with get_session() as session:
  15. step = PipelineStepRunRepository(session).get(step_run_id)
  16. if step is None:
  17. raise ValueError(f"step_run_id not found: {step_run_id}")
  18. run = PipelineRunRepository(session).get(step.run_id)
  19. if run is None:
  20. raise ValueError(f"pipeline run not found: {step.run_id}")
  21. context = StepContext(
  22. run_id=run.run_id,
  23. step_run_id=step.step_run_id,
  24. step_key=step.step_key,
  25. biz_dt=run.biz_dt,
  26. date_snapshot=dict(run.date_snapshot_json or {}),
  27. config_snapshot=dict(run.config_snapshot_json or {}),
  28. input_snapshot=dict(step.input_snapshot_json or {}),
  29. dry_run=bool(run.dry_run),
  30. )
  31. return execute_registered_step(context)
  32. def main() -> None:
  33. parser = argparse.ArgumentParser(description="Execute one durable pipeline step")
  34. parser.add_argument("step_run_id")
  35. parser.add_argument("--result-file", required=True)
  36. args = parser.parse_args()
  37. logging.basicConfig(
  38. level=logging.INFO,
  39. format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
  40. )
  41. result: dict[str, Any]
  42. exit_code = 0
  43. try:
  44. result = execute_step_run(args.step_run_id)
  45. if result.get("success") is False:
  46. exit_code = 1
  47. except Exception as exc:
  48. logger.exception("Pipeline step failed: step_run_id=%s", args.step_run_id)
  49. result = {"success": False, "error_code": "step_exception", "error": str(exc)}
  50. exit_code = 1
  51. finally:
  52. dispose_engine()
  53. Path(args.result_file).write_text(
  54. json.dumps(result, ensure_ascii=False, default=str),
  55. encoding="utf-8",
  56. )
  57. raise SystemExit(exit_code)
  58. if __name__ == "__main__":
  59. main()