run_task_executor_parallel.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. """Entry point to start N local Motor-CAD task executors (P3-M3 / P5-M2).
  2. Configurable via executor_config.json (see executor_config.py). This
  3. entry is kept for back-compat with the original --instances/--interval/
  4. --mock CLI and delegates to the shared config loader + executor builder
  5. in run_task_executor.
  6. Run in background:
  7. python scripts/run_task_executor_parallel.py --instances 3 --interval 5
  8. NOTE: All strings must be ASCII only.
  9. """
  10. import argparse
  11. import os
  12. import sys
  13. import time
  14. _SCRIPTS_DIR = os.path.dirname(os.path.abspath(__file__))
  15. if _SCRIPTS_DIR not in sys.path:
  16. sys.path.insert(0, _SCRIPTS_DIR)
  17. import executor_config # noqa: E402
  18. from run_task_executor import setup_logging, build_executors # noqa: E402
  19. def main():
  20. parser = argparse.ArgumentParser(
  21. description="Start N local Motor-CAD executors")
  22. parser.add_argument("--instances", type=int, default=None,
  23. help="number of parallel executor instances "
  24. "(overrides config)")
  25. parser.add_argument("--interval", type=int, default=None,
  26. help="poll interval in seconds (overrides config)")
  27. parser.add_argument("--mock", action="store_true",
  28. help="use mock solver (no Motor-CAD) for testing")
  29. parser.add_argument("--config", default=None,
  30. help="path to executor_config.json")
  31. args = parser.parse_args()
  32. cfg = executor_config.load_config(cli_path=args.config)
  33. if args.instances is not None:
  34. cfg["instances"] = args.instances
  35. if args.interval is not None:
  36. cfg["poll_interval"] = args.interval
  37. if args.mock:
  38. cfg["enable_mock"] = True
  39. executor_config.validate_config(cfg)
  40. if cfg["instances"] < 1:
  41. parser.error("--instances must be >= 1")
  42. log_file = setup_logging(cfg["log_dir"], cfg["log_level"])
  43. print("N=%d executors. Model=%s" % (cfg["instances"], cfg["model_path"]),
  44. flush=True)
  45. print("Web base URL: %s" % cfg["web_base_url"], flush=True)
  46. print("Log: %s" % log_file, flush=True)
  47. print("Ctrl+C to stop.", flush=True)
  48. executors = build_executors(cfg)
  49. threads = []
  50. for ex in executors:
  51. threads.append(ex.start_polling(interval=int(cfg["poll_interval"])))
  52. print("Executor started: %s" % ex.executor_id, flush=True)
  53. try:
  54. while any(t.is_alive() for t in threads):
  55. time.sleep(1)
  56. except KeyboardInterrupt:
  57. for ex in executors:
  58. ex.stop()
  59. ex.cleanup()
  60. print("All executors stopped.", flush=True)
  61. if __name__ == "__main__":
  62. main()