arthur/do

60 lines
1.7 KiB
Text
Raw Normal View History

#!/usr/bin/env python3
"""Run the local app and its frontend watcher with one command."""
import os
import signal
import socket
import subprocess
import sys
import time
from pathlib import Path
ROOT = Path(__file__).resolve().parent
def start():
with socket.socket() as probe:
if probe.connect_ex(("127.0.0.1", 8778)) == 0:
raise SystemExit("port 8778 is already in use")
commands = [
(["mise", "exec", "--", "python", "manage.py", "runserver", "8778"], ROOT),
(["mise", "exec", "--", "npx", "shadow-cljs", "watch", "app"], ROOT / "frontend"),
]
children = []
stopping = False
def stop(_signal, _frame):
nonlocal stopping
stopping = True
signal.signal(signal.SIGINT, stop)
signal.signal(signal.SIGTERM, stop)
try:
for command, directory in commands:
children.append(subprocess.Popen(command, cwd=directory, start_new_session=True))
print("arthur: http://localhost:8778 (Ctrl-C stops both processes)", flush=True)
while not stopping:
for child in children:
if child.poll() is not None:
raise SystemExit(f"app process exited with status {child.returncode}")
time.sleep(0.25)
finally:
for child in children:
if child.poll() is None:
os.killpg(child.pid, signal.SIGTERM)
for child in children:
try:
child.wait(timeout=5)
except subprocess.TimeoutExpired:
os.killpg(child.pid, signal.SIGKILL)
child.wait()
if __name__ == "__main__":
if sys.argv[1:] == ["start"]:
start()
else:
raise SystemExit("usage: ./do start")