DLC-Import Hang gefixt: kein sync-FS Log-I/O mehr pro Link
Symptom: Nutzer zieht DLC mit vielen Paketen rein, App haengt 1-2 min.
Ursache: addPackages() rief logPackageForItem() pro Link auf. Jede
dieser Calls triggerte ~10 synchrone FS-Operationen:
- ensurePackageLog: mkdirSync + existsSync
- ensureItemLog: mkdirSync + existsSync + writeFileSync (first-time)
+ 2× appendFileSync (first-time header)
- logPackage + writeItemLogEvent (appendFileSync, batched)
Bei einer DLC mit 60 Paketen × 25 Links = 1500 Items → ~9.000-15.000
sync FS-Calls. Auf langsamen Disks / Netzwerk-Shares: 60-120 Sekunden
Event-Loop-Blockade. UI eingefroren.
Fix: per-Item-Logs waehrend Bulk-Add nicht mehr initialisieren. Sie
werden lazy beim ersten echten Lifecycle-Event (Download-Start, Fehler)
angelegt. Stattdessen EINE zusammengefasste "Links registriert (N)"
Zeile ins Package-Log pro Paket — bei >50 Links mit gekuerzter
Vorschau (erste 20 + "+N more") damit die Log-Zeile nicht riesig wird.
Neuer Test "bulk-adds large DLC containers without initializing per-item
logs" verifiziert: 1500 Items werden in <5s hinzugefuegt (lokal unter
300ms), keine Item-Log-Dateien entstehen, pro Paket existiert genau ein
Package-Log.
This commit is contained in:
@@ -2746,6 +2746,11 @@ export class DownloadManager extends EventEmitter {
|
||||
linkCount: links.length
|
||||
});
|
||||
|
||||
// Collect per-link summary for ONE batched package-log entry after the
|
||||
// loop, instead of ~10 sync FS calls per link. A DLC with many packages
|
||||
// was freezing the UI for 1-2 minutes because logPackageForItem called
|
||||
// ensurePackageLog + ensureItemLog + appendFileSync×multiple per link.
|
||||
const registeredLinkSummary: string[] = [];
|
||||
for (let linkIdx = 0; linkIdx < links.length; linkIdx += 1) {
|
||||
const link = links[linkIdx];
|
||||
const itemId = uuidv4();
|
||||
@@ -2772,13 +2777,7 @@ export class DownloadManager extends EventEmitter {
|
||||
updatedAt: nowMs()
|
||||
};
|
||||
this.assignItemTargetPath(item, path.join(outputDir, fileName));
|
||||
this.logPackageForItem(item, "INFO", "Link registriert", {
|
||||
index: linkIdx + 1,
|
||||
totalLinks: links.length,
|
||||
url: link,
|
||||
hintedName: hintName || "",
|
||||
initialTargetPath: item.targetPath
|
||||
});
|
||||
registeredLinkSummary.push(`#${linkIdx + 1} ${fileName} <- ${link}`);
|
||||
packageEntry.itemIds.push(itemId);
|
||||
this.session.items[itemId] = item;
|
||||
this.itemCount += 1;
|
||||
@@ -2795,6 +2794,22 @@ export class DownloadManager extends EventEmitter {
|
||||
addedLinks += 1;
|
||||
}
|
||||
|
||||
// One batched log entry per package instead of one per link.
|
||||
// Item-logs are left uninitialized here — they'll be lazily created
|
||||
// the first time the item actually gets a real lifecycle event
|
||||
// (download start, error, etc.). For very large packages (>50 links)
|
||||
// we only log the first 20 + a "... +N more" suffix so the single log
|
||||
// line doesn't grow into hundreds of KB.
|
||||
if (registeredLinkSummary.length > 0) {
|
||||
const PREVIEW = 20;
|
||||
const linksField = registeredLinkSummary.length <= 50
|
||||
? registeredLinkSummary.join(" | ")
|
||||
: `${registeredLinkSummary.slice(0, PREVIEW).join(" | ")} | ... +${registeredLinkSummary.length - PREVIEW} more`;
|
||||
this.logPackageForPackage(packageEntry, "INFO", `Links registriert (${registeredLinkSummary.length})`, {
|
||||
links: linksField
|
||||
});
|
||||
}
|
||||
|
||||
this.session.packages[packageId] = packageEntry;
|
||||
this.session.packageOrder.push(packageId);
|
||||
addedPackages += 1;
|
||||
|
||||
Reference in New Issue
Block a user