fix: recover stuck background updates
TallyNote release / linux-x64 (push) Successful in 6m3s

This commit is contained in:
Qiufeng
2026-09-03 06:49:48 +08:00
parent b431fe167e
commit ee89e04aae
11 changed files with 331 additions and 36 deletions
+6
View File
@@ -59,6 +59,7 @@ import {
checkForUpdate,
publicCheckFromCache,
publicUpdateJob,
reconcileOrphanedUpdateJobs,
readCachedRelease,
writeUpdateRequest,
type UpdateRequest,
@@ -939,6 +940,7 @@ export async function buildApp(database: DatabaseContext, config: AppConfig) {
// Release metadata and task state should never be stored by an upstream
// proxy or a shared browser cache.
reply.header("Cache-Control", "no-store");
reconcileOrphanedUpdateJobs(database.sqlite, config);
const cached = publicCheckFromCache(database.sqlite, config);
const row = database.sqlite.prepare(`
SELECT id, operation, status, version, platform, asset_name AS assetName,
@@ -956,6 +958,7 @@ export async function buildApp(database: DatabaseContext, config: AppConfig) {
app.post("/api/update/check", { preHandler: guard(database, config), bodyLimit: 32 * 1024 }, async (request, reply) => {
try {
reconcileOrphanedUpdateJobs(database.sqlite, config);
// Disabled/dev installs do not contact a release endpoint, so repeated
// checks are local status reads and should remain immediately usable.
if (config.updateStrategy !== "disabled") {
@@ -995,6 +998,7 @@ export async function buildApp(database: DatabaseContext, config: AppConfig) {
let applyAuditRecorded = false;
let applyAuditTarget: string | undefined;
try {
reconcileOrphanedUpdateJobs(database.sqlite, config);
if (config.updateStrategy !== "systemd") {
throw new AppError(503, "UPDATE_NOT_AVAILABLE", "当前安装方式未启用一键更新,请使用命令行更新");
}
@@ -1145,6 +1149,7 @@ export async function buildApp(database: DatabaseContext, config: AppConfig) {
app.post("/api/update/download", { preHandler: guard(database, config), bodyLimit: 32 * 1024 }, async (request, reply) => {
const input = updateDownloadSchema.parse(request.body);
reconcileOrphanedUpdateJobs(database.sqlite, config);
if (config.updateStrategy !== "systemd") throw new AppError(503, "UPDATE_NOT_AVAILABLE", "当前安装方式未启用一键更新,请使用命令行更新");
const active = database.sqlite.prepare(`SELECT id FROM update_jobs WHERE status IN (${ACTIVE_UPDATE_STATUSES.map(() => "?").join(",")}) LIMIT 1`).get(...ACTIVE_UPDATE_STATUSES) as { id: string } | undefined;
if (active) throw new AppError(409, "UPDATE_IN_PROGRESS", "已有更新任务正在进行,请等待完成");
@@ -1175,6 +1180,7 @@ export async function buildApp(database: DatabaseContext, config: AppConfig) {
app.get("/api/update/jobs/:id", { preHandler: guard(database, config) }, async (request, reply) => {
const id = z.string().uuid().parse((request.params as { id: string }).id);
reconcileOrphanedUpdateJobs(database.sqlite, config);
const row = database.sqlite.prepare(`
SELECT id, operation, status, version, platform, asset_name AS assetName,
size_bytes AS sizeBytes, error_message AS errorMessage,