feat: refactor online update to synchronous web-process download
TallyNote release / linux-x64 (push) Failing after 3m12s
TallyNote release / linux-x64 (push) Failing after 3m12s
- Download happens in web process (non-root) with real-time progress - Root runner only handles privileged apply (stop/backup/switch/restart) - Eliminates 'waiting for system scheduler' stuck state - Frontend shows download bytes/speed/percentage with cancel button - Staged download triggers apply request file for root runner - systemd timeout reduced from 32min to 5min (no download phase) - Tests adapted for synchronous download flow release: 1.3.0
This commit is contained in:
+7
-4
@@ -65,6 +65,7 @@ import {
|
||||
readCachedRelease,
|
||||
writeUpdateRequest,
|
||||
cancelUpdateJob,
|
||||
downloadAndStageUpdate,
|
||||
type UpdateRequest,
|
||||
} from "./update-service.js";
|
||||
|
||||
@@ -1186,13 +1187,15 @@ export async function buildApp(database: DatabaseContext, config: AppConfig) {
|
||||
writeAudit(database.sqlite, { requestId: request.id, actorAdminId: request.auth!.admin.id, actorUsername: request.auth!.admin.username, action: "update.download_requested", targetType: "update", targetId: id, after: { version } });
|
||||
}).immediate();
|
||||
try {
|
||||
await writeUpdateRequest(config, { jobId: id, operation: "download", version, metadataUrl: cached.metadataUrl, assetUrl: cachedAsset.url, assetName: cachedAsset.name, expectedSha256: cachedAsset.sha256, requestedAt: now, currentLink: config.currentLink, releasesDir: config.releasesDir, dataDir: config.dataDir });
|
||||
// Download happens synchronously in the web process (non-root). The
|
||||
// root runner only receives an apply request after staging completes.
|
||||
void downloadAndStageUpdate(database.sqlite, config, id, request.auth!.admin.id, version, cachedAsset.url, cachedAsset.name, cachedAsset.sha256, cached.metadataUrl);
|
||||
} catch {
|
||||
database.sqlite.prepare("UPDATE update_jobs SET status='failed', error_message=?, updated_at=? WHERE id=?").run("无法创建系统更新请求", Date.now(), id);
|
||||
throw new AppError(503, "UPDATE_QUEUE_FAILED", "无法提交更新请求,请检查服务安装权限");
|
||||
database.sqlite.prepare("UPDATE update_jobs SET status='failed', error_message=?, updated_at=? WHERE id=?").run("无法启动下载", Date.now(), id);
|
||||
throw new AppError(503, "UPDATE_DOWNLOAD_FAILED", "无法启动下载,请稍后重试");
|
||||
}
|
||||
reply.header("Cache-Control", "no-store");
|
||||
return reply.code(202).send({ job: { id, status: "queued", operation: "download", version } });
|
||||
return reply.code(200).send({ job: { id, status: "downloading", operation: "download", version } });
|
||||
});
|
||||
|
||||
app.post("/api/update/cancel", { preHandler: guard(database, config) }, async (request, reply) => {
|
||||
|
||||
Reference in New Issue
Block a user