This commit is contained in:
2026-05-09 17:15:23 +08:00
parent 80a4183b45
commit a0ed128bde
43 changed files with 2573 additions and 381 deletions

View File

@@ -195,7 +195,7 @@ is_spacetime_ready() {
local server="$1"
local output
if output="$(spacetime server ping "${server}" 2>&1)" &&
if output="$(spacetime --root-dir="${SPACETIME_ROOT_DIR}" server ping "${server}" 2>&1)" &&
[[ "${output}" == *"Server is online:"* ]]; then
return 0
fi
@@ -345,6 +345,48 @@ prepare_migration_bootstrap_secret() {
echo "[dev:rust] 迁移引导密钥: ${MIGRATION_BOOTSTRAP_SECRET}"
}
is_sccache_wrapper_failure_log() {
local log_file="$1"
grep -Eiq \
'sccache: error|could not execute process.*sccache|Failed to send data to or receive data from server|Mismatch of client/server versions|Failed to read response header|failed to fill whole buffer' \
"${log_file}"
}
run_spacetime_publish_with_sccache_fallback() {
local root_dir="$1"
shift
local publish_log
publish_log="$(mktemp -t genarrative-spacetime-publish.XXXXXX.log)"
set +e
spacetime --root-dir="${root_dir}" "$@" 2> >(tee "${publish_log}" >&2)
local publish_status="$?"
set -e
if [[ "${publish_status}" -eq 0 ]]; then
rm -f "${publish_log}"
return 0
fi
if ! is_sccache_wrapper_failure_log "${publish_log}"; then
rm -f "${publish_log}"
return "${publish_status}"
fi
echo "[dev:rust] 检测到 sccache wrapper 通信异常,改用 rustc 直连重试 SpacetimeDB 发布。"
echo "[dev:rust] 这只影响本次 publish项目级 sccache 配置不会被修改。"
set +e
RUSTC_WRAPPER= CARGO_BUILD_RUSTC_WRAPPER= spacetime --root-dir="${root_dir}" "$@"
publish_status="$?"
set -e
rm -f "${publish_log}"
return "${publish_status}"
}
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd -- "${SCRIPT_DIR}/.." && pwd)"
SERVER_RS_DIR="${REPO_ROOT}/server-rs"
@@ -564,6 +606,7 @@ if [[ "${SKIP_SPACETIME}" -ne 1 ]]; then
# 当目标端口被占用时SpacetimeDB 会询问是否使用最近的可用端口;
# 这里直接发送回车接受默认建议,再从启动日志解析实际监听端口。
printf '\n' | spacetime \
--root-dir="${SPACETIME_ROOT_DIR}" \
start \
--data-dir "${SPACETIME_DATA_DIR}" \
--listen-addr "${SPACETIME_HOST}:${SPACETIME_PORT}" \
@@ -601,7 +644,9 @@ if [[ "${SKIP_PUBLISH}" -ne 1 ]]; then
cd "${SERVER_RS_DIR}"
# spacetime publish 会在内部调用 Cargo从 server-rs 目录执行,确保读取
# server-rs/.cargo/config.toml 中的 sccache/linker 配置,并复用同一套 target 缓存。
spacetime "${PUBLISH_ARGS[@]}"
# Windows 本地 sccache server 偶发通信异常时,保留 root-dir/target 缓存路径,
# 仅对重试子进程清空 Cargo wrapper避免可选缓存工具阻断真实构建。
run_spacetime_publish_with_sccache_fallback "${SPACETIME_ROOT_DIR}" "${PUBLISH_ARGS[@]}"
)
fi

View File

@@ -37,14 +37,30 @@ loadEnvFile(resolve(repoRoot, '.env'), fileEnv);
loadEnvFile(resolve(repoRoot, '.env.local'), fileEnv);
loadEnvFile(resolve(repoRoot, '.env.secrets.local'), fileEnv);
function buildTargetCandidates() {
function resolveConfiguredTarget() {
if (fileEnv.GENARRATIVE_RUNTIME_SERVER_TARGET) {
return fileEnv.GENARRATIVE_RUNTIME_SERVER_TARGET;
}
if (fileEnv.RUST_SERVER_TARGET) {
return fileEnv.RUST_SERVER_TARGET;
}
if (fileEnv.GENARRATIVE_API_TARGET) {
return fileEnv.GENARRATIVE_API_TARGET;
}
if (fileEnv.GENARRATIVE_API_PORT) {
return `http://127.0.0.1:${fileEnv.GENARRATIVE_API_PORT}`;
}
return '';
}
function buildFallbackCandidates() {
const candidates = [
fileEnv.GENARRATIVE_RUNTIME_SERVER_TARGET,
fileEnv.RUST_SERVER_TARGET,
fileEnv.GENARRATIVE_API_TARGET,
`http://127.0.0.1:${fileEnv.GENARRATIVE_API_PORT || '3100'}`,
'http://127.0.0.1:8082',
'http://127.0.0.1:3100',
'http://127.0.0.1:8082',
].filter(Boolean);
return Array.from(new Set(candidates));
@@ -70,39 +86,30 @@ async function isTargetReachable(target) {
}
async function resolveRuntimeTarget() {
const candidates = buildTargetCandidates();
const reachableTargets = [];
const configuredTarget = resolveConfiguredTarget();
for (const target of candidates) {
if (await isTargetReachable(target)) {
reachableTargets.push(target);
if (
target === fileEnv.GENARRATIVE_RUNTIME_SERVER_TARGET ||
target === fileEnv.RUST_SERVER_TARGET ||
target === fileEnv.GENARRATIVE_API_TARGET
) {
return {
target,
fallbackUsed: false,
};
}
}
}
if (reachableTargets.length > 0) {
if (configuredTarget) {
return {
target: reachableTargets[0],
fallbackUsed: true,
target: configuredTarget,
fallbackUsed: false,
targetUnavailable: !(await isTargetReachable(configuredTarget)),
};
}
for (const target of buildFallbackCandidates()) {
if (await isTargetReachable(target)) {
return {
target,
fallbackUsed: true,
targetUnavailable: false,
};
}
}
return {
target:
fileEnv.GENARRATIVE_RUNTIME_SERVER_TARGET ||
fileEnv.RUST_SERVER_TARGET ||
fileEnv.GENARRATIVE_API_TARGET ||
`http://127.0.0.1:${fileEnv.GENARRATIVE_API_PORT || '3100'}`,
target: 'http://127.0.0.1:3100',
fallbackUsed: false,
targetUnavailable: true,
};
}
@@ -113,6 +120,12 @@ if (runtimeTarget.fallbackUsed) {
);
}
if (runtimeTarget.targetUnavailable) {
console.warn(
`[dev:web] Rust target 当前不可用: ${runtimeTarget.target},请先启动 api-server。`,
);
}
const mergedEnv = {
...fileEnv,
RUST_SERVER_TARGET: runtimeTarget.target,