Fix: Start-Konflikt-Waechter friert nach Update nicht mehr die ganze Liste ein
Nach einem Auto-Update-Neustart blieb die komplette Warteschlange stehen
(running=false, hunderte Items wartend), obwohl Auto-Resume aktiv war.
Ursache war der Start-Konflikt-Waechter:
- getStartConflicts() meldete jedes Paket als Konflikt, dessen
paketspezifischer Entpack-Ordner bereits Dateien enthielt. Ein nur
teilweise heruntergeladenes Paket hat dort aber seine EIGENEN fertigen
Teile liegen (z.B. 15 von 26 fertig und entpackt) - das ist kein
Konflikt, sondern Wiederaufnahme.
- Der Auto-Resume-Waechter war binaer: ein einziger gemeldeter Konflikt
hat ALLE Pakete blockiert ("Auto-Resume uebersprungen: Start-Konflikte
erkannt"). Zwei teilfertige Pakete haben so 30 Pakete eingefroren.
Fix:
- Diskriminator in getStartConflicts(): ein Paket mit eigenen fertigen
("completed") Items zaehlt nicht mehr als Konflikt - die Dateien im
Entpack-Ordner sind seine eigene Ausgabe, kein Fremdbestand.
- Selektives Auto-Resume: start() akzeptiert excludePackageIds und laesst
diese Pakete aus dem Lauf-Set (runPackageIds, auf das der Scheduler
filtert). beginAutoResume() startet die sauberen Pakete und haelt nur
echte Konflikte zurueck, statt alles zu blockieren; die zurueckgehaltenen
Pakete werden im Log namentlich genannt.
Die beiden Aenderungen greifen ineinander: der Diskriminator garantiert,
dass ein als Konflikt gemeldetes Paket keine fertigen Teile hat, also auch
keine ausstehende Nachbearbeitung - das defensive runPackageIds.delete kann
daher keine Entpack-Arbeit haengen lassen.
Tests: Diskriminator (eigene Ausgabe nicht geflaggt / Fremdbestand
geflaggt) plus selektives Resume (ausgeschlossenes Paket bleibt aus dem
Lauf-Set, laeuft nicht an).
This commit is contained in:
+22
-17
@@ -180,21 +180,13 @@ export class AppController {
|
||||
if (this.settings.autoResumeOnStart) {
|
||||
const snapshot = this.manager.getSnapshot();
|
||||
const hasPending = Object.values(snapshot.session.items).some((item) => item.status === "queued" || item.status === "reconnect_wait");
|
||||
if (hasPending) {
|
||||
void this.manager.getStartConflicts().then((conflicts) => {
|
||||
const hasConflicts = conflicts.length > 0;
|
||||
if (this.hasAnyProviderToken(this.settings) && !hasConflicts) {
|
||||
if (this.onStateHandler) {
|
||||
logger.info("Auto-Resume beim Start aktiviert (nach Konflikt-Check)");
|
||||
void this.manager.start().catch((err) => logger.warn(`Auto-Resume Start Fehler: ${String(err)}`));
|
||||
} else {
|
||||
this.autoResumePending = true;
|
||||
logger.info("Auto-Resume beim Start vorgemerkt");
|
||||
}
|
||||
} else if (hasConflicts) {
|
||||
logger.info("Auto-Resume übersprungen: Start-Konflikte erkannt");
|
||||
}
|
||||
}).catch((err) => logger.warn(`getStartConflicts Fehler (constructor): ${String(err)}`));
|
||||
if (hasPending && this.hasAnyProviderToken(this.settings)) {
|
||||
if (this.onStateHandler) {
|
||||
this.beginAutoResume();
|
||||
} else {
|
||||
this.autoResumePending = true;
|
||||
logger.info("Auto-Resume beim Start vorgemerkt");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -251,14 +243,27 @@ export class AppController {
|
||||
handler(this.manager.getSnapshot());
|
||||
if (this.autoResumePending) {
|
||||
this.autoResumePending = false;
|
||||
void this.manager.start().catch((err) => logger.warn(`Auto-Resume Start Fehler: ${String(err)}`));
|
||||
logger.info("Auto-Resume beim Start aktiviert");
|
||||
this.beginAutoResume();
|
||||
} else {
|
||||
this.manager.triggerIdleExtractions();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private beginAutoResume(): void {
|
||||
void this.manager.getStartConflicts().then((conflicts) => {
|
||||
const excludePackageIds = new Set(conflicts.map((conflict) => conflict.packageId));
|
||||
if (excludePackageIds.size > 0) {
|
||||
const names = conflicts.map((conflict) => conflict.packageName).join(", ");
|
||||
logger.info(`Auto-Resume: ${excludePackageIds.size} Paket(e) mit Start-Konflikt zurückgehalten (${names}); übrige Pakete starten`);
|
||||
} else {
|
||||
logger.info("Auto-Resume beim Start aktiviert (keine Start-Konflikte)");
|
||||
}
|
||||
void this.manager.start(excludePackageIds.size > 0 ? { excludePackageIds } : undefined)
|
||||
.catch((err) => logger.warn(`Auto-Resume Start Fehler: ${String(err)}`));
|
||||
}).catch((err) => logger.warn(`Auto-Resume Konflikt-Check Fehler: ${String(err)}`));
|
||||
}
|
||||
|
||||
public getSnapshot(): UiSnapshot {
|
||||
return this.manager.getSnapshot();
|
||||
}
|
||||
|
||||
@@ -3011,6 +3011,14 @@ export class DownloadManager extends EventEmitter {
|
||||
continue;
|
||||
}
|
||||
|
||||
const hasOwnCompletedOutput = pkg.itemIds.some((itemId) => {
|
||||
const item = this.session.items[itemId];
|
||||
return Boolean(item && item.status === "completed");
|
||||
});
|
||||
if (hasOwnCompletedOutput) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!this.isPackageSpecificExtractDir(pkg)) {
|
||||
continue;
|
||||
}
|
||||
@@ -5562,7 +5570,7 @@ export class DownloadManager extends EventEmitter {
|
||||
});
|
||||
}
|
||||
|
||||
public async start(): Promise<void> {
|
||||
public async start(options?: { excludePackageIds?: ReadonlySet<string> }): Promise<void> {
|
||||
if (this.session.running) {
|
||||
return;
|
||||
}
|
||||
@@ -5603,6 +5611,9 @@ export class DownloadManager extends EventEmitter {
|
||||
if (item.status !== "queued" && item.status !== "reconnect_wait") {
|
||||
return false;
|
||||
}
|
||||
if (options?.excludePackageIds?.has(item.packageId)) {
|
||||
return false;
|
||||
}
|
||||
const pkg = this.session.packages[item.packageId];
|
||||
return Boolean(pkg && !pkg.cancelled && pkg.enabled);
|
||||
});
|
||||
@@ -5670,6 +5681,11 @@ export class DownloadManager extends EventEmitter {
|
||||
this.itemContributedBytes.clear();
|
||||
this.reservedTargetPaths.clear();
|
||||
this.claimedTargetPathByItem.clear();
|
||||
if (options?.excludePackageIds) {
|
||||
for (const excluded of options.excludePackageIds) {
|
||||
this.runPackageIds.delete(excluded);
|
||||
}
|
||||
}
|
||||
|
||||
this.session.running = true;
|
||||
this.session.paused = false;
|
||||
|
||||
Reference in New Issue
Block a user