feat: workerize external generation

This commit is contained in:
2026-06-05 17:29:08 +08:00
parent 5150925947
commit 8d54ea3374
60 changed files with 5285 additions and 700 deletions

View File

@@ -5,10 +5,11 @@ set -euo pipefail
usage() {
cat <<'EOF'
用法:
./scripts/deploy/production-api-deploy.sh --source-dir build/<version> [--version <version>] [--release-root /opt/genarrative/releases] [--current-link /opt/genarrative/current] [--service genarrative-api.service] [--health-url http://127.0.0.1:8082/readyz] [--api-env-file /etc/genarrative/api-server.env] [--database genarrative-prod] [--spacetime-server-url http://127.0.0.1:3101]
./scripts/deploy/production-api-deploy.sh --source-dir build/<version> [--version <version>] [--release-root /opt/genarrative/releases] [--current-link /opt/genarrative/current] [--service genarrative-api.service] [--worker-service-pattern 'genarrative-external-generation-worker@*.service'] [--no-worker-services] [--health-url http://127.0.0.1:8082/readyz] [--api-env-file /etc/genarrative/api-server.env] [--database genarrative-prod] [--spacetime-server-url http://127.0.0.1:3101]
说明:
进入维护模式,校验并发布 api-server 单文件,更新 current 链接,重启 systemd 服务并执行 readiness 检查。
默认同时重启已加载的外部生成 worker 实例;未启用 worker 单元时会自动跳过。
若传入 --database会在重启前把 GENARRATIVE_SPACETIME_DATABASE 写入 api-server 环境文件,避免服务继续读取旧库。
失败时保留维护模式。
EOF
@@ -223,12 +224,106 @@ ensure_runtime_env_and_dirs() {
fi
}
list_worker_services() {
local pattern="$1"
if [[ -z "${pattern}" ]]; then
return 0
fi
systemctl list-units --all --plain --no-legend "${pattern}" 2>/dev/null | awk '{print $1}' | sort -u
}
ensure_default_worker_service() {
local pattern="$1"
local default_service="genarrative-external-generation-worker@1.service"
local template_service="genarrative-external-generation-worker@.service"
local services=()
if [[ -z "${pattern}" ]]; then
return 0
fi
if [[ "${pattern}" != "genarrative-external-generation-worker@*.service" ]]; then
return 0
fi
if ! systemctl cat "${template_service}" >/dev/null 2>&1; then
echo "[production-api-deploy] 缺少外部生成 worker systemd 模板: ${template_service}" >&2
return 1
fi
mapfile -t services < <(list_worker_services "${pattern}")
if [[ "${#services[@]}" -gt 0 ]]; then
return 0
fi
echo "[production-api-deploy] 未发现外部生成 worker 实例,启用并启动默认实例: ${default_service}"
systemctl enable --now "${default_service}"
}
restart_worker_services() {
local pattern="$1"
local services=()
if [[ -z "${pattern}" ]]; then
echo "[production-api-deploy] 跳过外部生成 worker 重启。"
return 0
fi
ensure_default_worker_service "${pattern}"
mapfile -t services < <(list_worker_services "${pattern}")
if [[ "${#services[@]}" -eq 0 ]]; then
echo "[production-api-deploy] 未发现已加载的外部生成 worker 单元: ${pattern}" >&2
return 1
fi
echo "[production-api-deploy] 重启外部生成 worker: ${services[*]}"
systemctl restart "${services[@]}"
}
wait_for_worker_services() {
local pattern="$1"
local services=()
local all_active
if [[ -z "${pattern}" ]]; then
return 0
fi
mapfile -t services < <(list_worker_services "${pattern}")
if [[ "${#services[@]}" -eq 0 ]]; then
echo "[production-api-deploy] 外部生成 worker 单元不存在,发布失败: ${pattern}" >&2
return 1
fi
echo "[production-api-deploy] 等待外部生成 worker active: ${services[*]}"
for _ in {1..30}; do
all_active=1
for service in "${services[@]}"; do
if ! systemctl is-active --quiet "${service}"; then
all_active=0
break
fi
done
if [[ "${all_active}" -eq 1 ]]; then
return 0
fi
sleep 2
done
systemctl --no-pager --full status "${services[@]}" || true
echo "[production-api-deploy] 外部生成 worker 未在超时时间内进入 active发布失败。" >&2
return 1
}
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
SOURCE_DIR=""
VERSION=""
RELEASE_ROOT="/opt/genarrative/releases"
CURRENT_LINK="/opt/genarrative/current"
SERVICE_NAME="genarrative-api.service"
WORKER_SERVICE_PATTERN="genarrative-external-generation-worker@*.service"
HEALTH_URL="http://127.0.0.1:8082/readyz"
API_ENV_FILE="/etc/genarrative/api-server.env"
DATABASE=""
@@ -261,6 +356,14 @@ while [[ $# -gt 0 ]]; do
SERVICE_NAME="${2:?缺少 --service 的值}"
shift 2
;;
--worker-service-pattern)
WORKER_SERVICE_PATTERN="${2:?缺少 --worker-service-pattern 的值}"
shift 2
;;
--no-worker-services)
WORKER_SERVICE_PATTERN=""
shift
;;
--health-url)
HEALTH_URL="${2:?缺少 --health-url 的值}"
shift 2
@@ -362,6 +465,8 @@ ln -sfn "${RELEASE_DIR}" "${CURRENT_LINK}"
echo "[production-api-deploy] 重启服务: ${SERVICE_NAME}"
systemctl restart "${SERVICE_NAME}"
restart_worker_services "${WORKER_SERVICE_PATTERN}"
wait_for_worker_services "${WORKER_SERVICE_PATTERN}"
echo "[production-api-deploy] 等待 readiness: ${HEALTH_URL}"
for _ in {1..30}; do