fix(dev): accept spacetime port fallback
Some checks failed
CI / verify (pull_request) Has been cancelled

This commit is contained in:
2026-05-08 18:15:48 +08:00
parent 26a3c89d1d
commit 621bf6506c
2 changed files with 88 additions and 32 deletions

View File

@@ -19,7 +19,7 @@ usage() {
1. 默认同时启动 SpacetimeDB standalone、Rust api-server、主站 Vite 与后台 Vite。
2. 当前开发阶段默认 publish server-rs/crates/spacetime-module 时追加 -c=on-conflict 在结构冲突时清理旧模块数据。
3. 只有显式传入 --preserve-database 时,才会跳过 -c=on-conflict。
4. SpacetimeDB 默认使用 server-rs/.spacetimedb/local/data 作为本地数据目录。
4. SpacetimeDB 默认使用 server-rs/.spacetimedb/local/data 作为本地数据目录;端口被占用时自动接受 SpacetimeDB 建议的最近可用端口
5. 默认在发布模块前随机生成迁移引导密钥,注入 GENARRATIVE_SPACETIME_MIGRATION_BOOTSTRAP_SECRET 并显示在控制台。
EOF
}
@@ -95,6 +95,47 @@ wait_for_spacetime() {
exit 1
}
wait_for_spacetime_listen_addr() {
local log_file="$1"
local timeout_seconds="$2"
local process_pid="${3:-}"
local deadline=$((SECONDS + timeout_seconds))
local listen_addr=""
while ((SECONDS < deadline)); do
if [[ -f "${log_file}" ]]; then
listen_addr="$(sed -n 's/^.*Starting SpacetimeDB listening on \([^[:space:]]\+\).*$/\1/p' "${log_file}" | tail -n 1)"
if [[ -n "${listen_addr}" ]]; then
echo "${listen_addr}"
return
fi
fi
if [[ -n "${process_pid}" ]] && ! kill -0 "${process_pid}" 2>/dev/null; then
echo "[dev:rust] SpacetimeDB 进程在输出监听地址前退出。" >&2
if [[ -f "${log_file}" ]]; then
echo "[dev:rust] 最近 SpacetimeDB 启动日志: ${log_file}" >&2
tail -n 80 "${log_file}" >&2 || true
fi
exit 1
fi
sleep 0.2
done
echo "[dev:rust] 等待 SpacetimeDB 输出监听地址超时。" >&2
if [[ -f "${log_file}" ]]; then
echo "[dev:rust] 最近 SpacetimeDB 启动日志: ${log_file}" >&2
tail -n 80 "${log_file}" >&2 || true
fi
exit 1
}
port_from_listen_addr() {
local listen_addr="$1"
echo "${listen_addr##*:}"
}
is_spacetime_ready() {
local server="$1"
local output
@@ -150,7 +191,9 @@ describe_spacetime_root_owner() {
# Windows 本地开发最常见的失败是同一个 data-dir 下已有 standalone 持有 spacetime.pid
# 启动前先打印占用进程,避免用户只看到底层 os error 33 而不知道该停哪个实例。
if command -v powershell.exe >/dev/null 2>&1; then
# 只有 Windows/Git Bash 风格路径才交给 PowerShell 查 Windows 进程;
# WSL/Linux 的 /tmp、/home 路径不能直接拿去匹配 Windows CommandLine容易误命中无关 spacetime 进程。
if command -v powershell.exe >/dev/null 2>&1 && [[ "${data_dir}" =~ ^/([a-zA-Z])/ ]]; then
DATA_DIR_FOR_POWERSHELL="${windows_data_dir}" powershell.exe -NoProfile -Command '
$dataDir = $env:DATA_DIR_FOR_POWERSHELL
$normalized = $dataDir.Replace("/", "\")
@@ -449,29 +492,34 @@ echo "[dev:rust] api timeout: ${API_SERVER_TIMEOUT_SECONDS}s"
if [[ "${SKIP_SPACETIME}" -ne 1 ]]; then
mkdir -p "${SPACETIME_ROOT_DIR}" "${SPACETIME_DATA_DIR}"
if is_spacetime_ready "${SPACETIME_SERVER}"; then
echo "[dev:rust] 复用已运行的 SpacetimeDB: ${SPACETIME_SERVER}"
else
SPACETIME_ROOT_OWNER="$(describe_spacetime_root_owner "${SPACETIME_DATA_DIR}")"
if [[ -n "${SPACETIME_ROOT_OWNER}" ]]; then
echo "[dev:rust] 当前 data-dir 已被其他 SpacetimeDB 实例占用,无法再次启动。" >&2
echo "[dev:rust] 目标地址未就绪: ${SPACETIME_SERVER}" >&2
echo "[dev:rust] 如需复用,请传入占用实例实际端口,例如 --spacetime-port 3199如需重启请先停止下列进程。" >&2
echo "${SPACETIME_ROOT_OWNER}" >&2
exit 1
fi
echo "[dev:rust] 启动 spacetimedb"
(
cd "${SERVER_RS_DIR}"
exec spacetime \
start \
--data-dir "${SPACETIME_DATA_DIR}" \
--non-interactive \
--listen-addr "${SPACETIME_HOST}:${SPACETIME_PORT}"
) &
PIDS+=("$!")
NAMES+=("spacetimedb")
SPACETIME_ROOT_OWNER="$(describe_spacetime_root_owner "${SPACETIME_DATA_DIR}")"
if [[ -n "${SPACETIME_ROOT_OWNER}" ]]; then
echo "[dev:rust] 当前 data-dir 已被其他 SpacetimeDB 实例占用,无法再次启动。" >&2
echo "[dev:rust] 如需复用,请传入占用实例实际端口并追加 --skip-spacetime如需重启请先停止下列进程。" >&2
echo "${SPACETIME_ROOT_OWNER}" >&2
exit 1
fi
SPACETIME_START_LOG="${SPACETIME_DATA_DIR}/logs/dev-rust-spacetime-start.log"
mkdir -p "$(dirname -- "${SPACETIME_START_LOG}")"
: >"${SPACETIME_START_LOG}"
echo "[dev:rust] 启动 spacetimedb"
(
cd "${SERVER_RS_DIR}"
# 当目标端口被占用时SpacetimeDB 会询问是否使用最近的可用端口;
# 这里直接发送回车接受默认建议,再从启动日志解析实际监听端口。
printf '\n' | spacetime \
start \
--data-dir "${SPACETIME_DATA_DIR}" \
--listen-addr "${SPACETIME_HOST}:${SPACETIME_PORT}"
) 2>&1 | tee "${SPACETIME_START_LOG}" &
PIDS+=("$!")
NAMES+=("spacetimedb")
SPACETIME_LISTEN_ADDR="$(wait_for_spacetime_listen_addr "${SPACETIME_START_LOG}" "${SPACETIME_TIMEOUT_SECONDS}" "${PIDS[0]:-}")"
SPACETIME_PORT="$(port_from_listen_addr "${SPACETIME_LISTEN_ADDR}")"
SPACETIME_SERVER="http://${SPACETIME_HOST}:${SPACETIME_PORT}"
echo "[dev:rust] spacetime actual: ${SPACETIME_SERVER}"
fi
if [[ "${SKIP_PUBLISH}" -ne 1 ]]; then
@@ -493,7 +541,7 @@ if [[ "${SKIP_PUBLISH}" -ne 1 ]]; then
PUBLISH_ARGS+=(--yes)
echo "[dev:rust] 发布 SpacetimeDB 模块: ${DATABASE}"
spacetime --root-dir="${SPACETIME_ROOT_DIR}" "${PUBLISH_ARGS[@]}"
spacetime "${PUBLISH_ARGS[@]}"
fi
echo "[dev:rust] 启动 api-server"