Save uncommitted changes
Build / Lint & Test (push) Successful in 19s

This commit is contained in:
PickleRick committed 2026-09-21 22:48:11 +02:00
1 parent febd68973b
commit 594889ea10
6 files changed
+60 -19

No files matched your search

+33 -14
View File
@@ -2,14 +2,13 @@
const fs = require('fs');
const COPY_BUFFER_SIZE = 4 * 1024 * 1024;
const copyWithProgress = async ({
source,
destination,
jobLog,
updateProgress,
label,
copyMethod = 'auto',
maxRetries = 2,
retryDelayMs = 1000,
}) => {
@@ -27,16 +26,12 @@ const copyWithProgress = async ({
if (typeof jobLog === 'function') jobLog(`${message}\n`);
};
const copyOnce = () => new Promise((resolve, reject) => {
const copyOnceWithStream = () => new Promise((resolve, reject) => {
const startMs = Date.now();
let copiedBytes = 0;
let nextProgressPercent = 0;
// Larger buffers avoid issuing thousands of small writes when the
// destination is an SMB/CIFS mount with noticeable round-trip latency.
const rd = fs.createReadStream(source, { highWaterMark: COPY_BUFFER_SIZE });
const wr = fs.createWriteStream(destination, {
highWaterMark: COPY_BUFFER_SIZE,
});
const rd = fs.createReadStream(source, { highWaterMark: 4 * 1024 * 1024 });
const wr = fs.createWriteStream(destination, { highWaterMark: 4 * 1024 * 1024 });
let settled = false;
const fail = (error) => {
if (settled) return;
@@ -45,7 +40,6 @@ const copyWithProgress = async ({
wr.destroy();
reject(error);
};
rd.on('error', fail);
wr.on('error', fail);
wr.on('finish', () => {
@@ -57,20 +51,45 @@ const copyWithProgress = async ({
copiedBytes += chunk.length;
const percent = sourceSize === 0 ? 100 : Math.floor((copiedBytes / sourceSize) * 100);
if (percent < nextProgressPercent) return;
const elapsedSeconds = Math.max((Date.now() - startMs) / 1000, 0.1);
const copiedMb = (copiedBytes / 1024 / 1024).toFixed(1);
const speedMbPerSecond = (copiedBytes / 1024 / 1024 / elapsedSeconds).toFixed(1);
report(
percent,
`[${label}] Progress: ${Math.min(percent, 100)}% `
+ `(${copiedMb}/${sourceSizeMb} MB, ${speedMbPerSecond} MB/s)`,
+ `(${(copiedBytes / 1024 / 1024).toFixed(1)}/${sourceSizeMb} MB, `
+ `${(copiedBytes / 1024 / 1024 / elapsedSeconds).toFixed(1)} MB/s)`,
);
nextProgressPercent = (Math.floor(percent / 10) + 1) * 10;
});
rd.pipe(wr);
});
const copyOnceWithNative = () => new Promise((resolve, reject) => {
const startMs = Date.now();
let settled = false;
const progressTimer = setInterval(() => {
if (settled || !fs.existsSync(destination)) return;
const copiedBytes = fs.statSync(destination).size;
const elapsedSeconds = Math.max((Date.now() - startMs) / 1000, 0.1);
report(
Math.floor((copiedBytes / sourceSize) * 100),
`[${label}] Progress: ${Math.min(Math.floor((copiedBytes / sourceSize) * 100), 100)}% `
+ `(${(copiedBytes / 1024 / 1024).toFixed(1)}/${sourceSizeMb} MB, `
+ `${(copiedBytes / 1024 / 1024 / elapsedSeconds).toFixed(1)} MB/s)`,
);
}, 1000);
fs.promises.copyFile(source, destination).then(() => {
settled = true;
clearInterval(progressTimer);
resolve(((Date.now() - startMs) / 1000).toFixed(1));
}).catch((error) => {
settled = true;
clearInterval(progressTimer);
reject(error);
});
});
const copyOnce = copyMethod === 'stream' ? copyOnceWithStream : copyOnceWithNative;
let lastError;
for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
if (attempt > 0) {