feat: add deployment configuration and scripts for managed-portal, including Dockerfiles and environment settings

This commit is contained in:
2026-05-13 16:49:21 +08:00
parent 330373b8f1
commit f8a6d9803d
13 changed files with 563 additions and 71 deletions

View File

@@ -8,8 +8,15 @@ OUTPUT_DIR="${OUTPUT_DIR:-${PROJECT_DIR}/outputs}"
RTSP_URL="${RTSP_URL:-}"
API_HOST="${API_HOST:-0.0.0.0}"
API_PORT="${API_PORT:-18082}"
RTSP_STALL_TIMEOUT_SECONDS="${RTSP_STALL_TIMEOUT_SECONDS:-180}"
DEEPFACE_CACHE_DIR="/root/.deepface/weights"
DEEPFACE_SOURCE_DIR="${PROJECT_DIR}/weights/deepface"
mkdir -p "${OUTPUT_DIR}" "$(dirname "${CONFIG_PATH}")"
mkdir -p "${OUTPUT_DIR}" "$(dirname "${CONFIG_PATH}")" "${DEEPFACE_CACHE_DIR}"
if [ -d "${DEEPFACE_SOURCE_DIR}" ]; then
find "${DEEPFACE_SOURCE_DIR}" -maxdepth 1 -name '*.h5' -exec cp {} "${DEEPFACE_CACHE_DIR}/" \;
fi
if [ ! -f "${CONFIG_PATH}" ]; then
cp "${CONFIG_TEMPLATE}" "${CONFIG_PATH}"
@@ -37,13 +44,31 @@ config_path.write_text(
)
PY
exec python - "$CONFIG_PATH" "$API_HOST" "$API_PORT" <<'PY'
RTSP_OUTPUT_SUBDIR="$(python - "$CONFIG_PATH" <<'PY'
from pathlib import Path
import sys
import yaml
config_path = Path(sys.argv[1])
raw = yaml.safe_load(config_path.read_text(encoding="utf-8")) or {}
rtsp = raw.get("rtsp") or {}
print(rtsp.get("output_subdir", "rtsp_stream"))
PY
)"
RTSP_STATUS_PATH="${OUTPUT_DIR}/${RTSP_OUTPUT_SUBDIR}/worker_status.json"
exec python - "$CONFIG_PATH" "$API_HOST" "$API_PORT" "$RTSP_STATUS_PATH" "$RTSP_STALL_TIMEOUT_SECONDS" <<'PY'
from pathlib import Path
import signal
import subprocess
import sys
import time
config_path, api_host, api_port = sys.argv[1:4]
from src.people_flow.worker_status import worker_status_stall_reason
config_path, api_host, api_port, status_path_raw, stall_timeout_raw = sys.argv[1:6]
status_path = Path(status_path_raw)
stall_timeout_seconds = max(float(stall_timeout_raw), 30.0)
commands = [
[sys.executable, "main.py", "--config", config_path, "rtsp"],
[
@@ -59,21 +84,38 @@ commands = [
],
]
processes = [subprocess.Popen(command) for command in commands]
supervisor_started_at = time.time()
def terminate_all(signum, _frame):
for process in processes:
if process.poll() is None:
process.terminate()
def stop_all(excluded_index=None):
for index, process in enumerate(processes):
if index == excluded_index or process.poll() is not None:
continue
process.terminate()
deadline = time.time() + 10
for process in processes:
if process.poll() is not None:
for index, process in enumerate(processes):
if index == excluded_index or process.poll() is not None:
continue
timeout = max(0, deadline - time.time())
try:
process.wait(timeout=timeout)
except subprocess.TimeoutExpired:
process.kill()
def stale_reason():
if processes[0].poll() is not None:
return None
return worker_status_stall_reason(
status_path,
started_at=supervisor_started_at,
max_age_seconds=stall_timeout_seconds,
)
def terminate_all(signum, _frame):
stop_all()
raise SystemExit(128 + signum)
@@ -85,19 +127,12 @@ while True:
return_code = process.poll()
if return_code is None:
continue
for other_index, other_process in enumerate(processes):
if other_index == index or other_process.poll() is not None:
continue
other_process.terminate()
deadline = time.time() + 10
for other_index, other_process in enumerate(processes):
if other_index == index or other_process.poll() is not None:
continue
timeout = max(0, deadline - time.time())
try:
other_process.wait(timeout=timeout)
except subprocess.TimeoutExpired:
other_process.kill()
stop_all(excluded_index=index)
raise SystemExit(return_code)
reason = stale_reason()
if reason is not None:
print(reason, flush=True)
stop_all()
raise SystemExit(1)
time.sleep(0.5)
PY