修复冷备份后 API 恢复

备份脚本支持冷备份后重启依赖服务

生产备份与发布脚本恢复 genarrative-api 服务

api-server 启动恢复 SpacetimeDB 超时后持续重试

同步更新后端与运维文档口径
This commit is contained in:
kdletters
2026-06-09 12:35:27 +08:00
parent c9c66f046b
commit 568509027c
6 changed files with 60 additions and 10 deletions

View File

@@ -20,7 +20,7 @@ const UNSIGNED_PAYLOAD = 'UNSIGNED-PAYLOAD';
function usage() {
console.log(`用法:
npm run database:backup:oss -- [--data-dir <path>] [--work-dir <path>] [--bucket <bucket>] [--object-prefix <prefix>] [--keep-local]
node scripts/database-backup-to-oss.mjs [--stop-service spacetimedb.service] [--defer-upload]
node scripts/database-backup-to-oss.mjs [--stop-service spacetimedb.service] [--restart-service-after genarrative-api.service] [--defer-upload]
node scripts/database-backup-to-oss.mjs --upload-archive <path>
说明:
@@ -100,6 +100,7 @@ function parseArgs(argv) {
envFiles: [],
keepLocal: false,
stopService: '',
restartServicesAfter: [],
database: '',
dryRun: false,
deferUpload: false,
@@ -159,6 +160,9 @@ function parseArgs(argv) {
case '--stop-service':
options.stopService = readValue();
break;
case '--restart-service-after':
options.restartServicesAfter.push(readValue());
break;
case '--keep-local':
options.keepLocal = true;
break;
@@ -266,6 +270,16 @@ function startServiceIfNeeded(serviceName, wasStopped) {
runCommand('systemctl', ['start', serviceName], {stdio: 'inherit'});
}
function restartServicesAfterBackup(serviceNames) {
for (const serviceName of serviceNames) {
if (!serviceName) {
continue;
}
console.log(`[database-backup] 冷备份后重启依赖服务: ${serviceName}`);
runCommand('systemctl', ['restart', serviceName], {stdio: 'inherit'});
}
}
function createArchive({dataDir, workDir, fileName}) {
if (!existsSync(dataDir)) {
throw new Error(`数据库数据目录不存在: ${dataDir}`);
@@ -510,6 +524,13 @@ async function main() {
} finally {
startServiceIfNeeded(args.stopService || firstNonEmpty(env.GENARRATIVE_DATABASE_BACKUP_STOP_SERVICE), serviceStopped);
}
restartServicesAfterBackup([
...String(env.GENARRATIVE_DATABASE_BACKUP_RESTART_SERVICE_AFTER ?? '')
.split(',')
.map((value) => value.trim())
.filter(Boolean),
...args.restartServicesAfter,
]);
const manifestPath = `${archivePath}.manifest.json`;
writeManifest({