fix: stabler ETA for uploads

Massimo Melina committed Jul 18, 2025 at 22:53 UTC ed5738dd52b3c81d800a16d34a5b98d052fd0b32
2 files changed +10 -3
frontend/src/upload.ts
+1 -1
@@ -48,7 +48,7 @@ export function showUpload() {
48 function Content(){
49 const { qs, paused, eta, speed, adding } = useSnapshot(uploadState) as Readonly<typeof uploadState>
50 const { props, uploadOnExisting } = useSnapState()
51 - const etaStr = useMemo(() => !eta ? '' : formatTime(eta*1000, 0, 2), [eta])
51 + const etaStr = useMemo(() => !eta || eta === Infinity ? '' : formatTime(eta*1000, 0, 2), [eta])
52 const inQ = _.sumBy(qs, q => q.entries.length) - (uploadState.uploading ? 1 : 0)
53 const queueStr = inQ && t('in_queue', { n: inQ }, "{n} in queue")
54 const size = formatBytes(adding.reduce((a, x) => a + x.file.size, 0))
frontend/src/uploadQueue.ts
+9 -2
@@ -54,10 +54,11 @@ let stuckSince = Infinity
54 // keep track of speed
55 let bytesSentTimestamp = Date.now()
56 let bytesSent = 0
57 +const recentSpeedSamples: number[] = []
58 setInterval(() => {
59 const now = Date.now()
60 const passed = (now - bytesSentTimestamp) / 1000
60 - uploadState.speed = bytesSent / passed
61 + const speed = bytesSent / passed
62 if (currentReq && now - stuckSince >= 10_000) { // this will normally cause the upload to be retried after long time of no progress
63 currentReq.abort()
64 console.debug('upload stuck, aborting')
@@ -68,7 +69,13 @@ setInterval(() => {
69 // keep track of ETA
70 const qBytes = _.sumBy(uploadState.qs, q => _.sumBy(q.entries, x => x.file.size))
71 const left = (qBytes - uploadState.partial)
71 - uploadState.eta = uploadState.speed && Math.round(left / uploadState.speed)
72 + const doSample = uploadState.uploading
73 + if (doSample)
74 + recentSpeedSamples.push(speed)
75 + if (!doSample || recentSpeedSamples.length > 5) // max 5 samples, 10 seconds
76 + recentSpeedSamples.shift()
77 + uploadState.speed = _.mean(recentSpeedSamples)
78 + uploadState.eta = left / uploadState.speed
79 }, 2_000)
80
81 let currentReq: XMLHttpRequest | undefined