retry upload after it's stopped for 20 seconds #844
Massimo Melina committed
Jan 2, 2025 at 15:15 UTC
f153653291ca0fbc0551299b3bc9eed09003bab4
1 file changed
+19
-6
frontend/src/uploadQueue.ts
+19
-6
@@ -51,6 +51,8 @@ window.onbeforeunload = ev => {
51
return ev.returnValue = t("Uploading") // modern browsers ignore this message
52
}
53
54
+const RETRY_UPLOAD = -1
55
+let stuckSince = Infinity
56
// keep track of speed
57
let bytesSentTimestamp = Date.now()
58
let bytesSent = 0
@@ -59,6 +61,10 @@ setInterval(() => {
61
const passed = (now - bytesSentTimestamp) / 1000
62
if (passed < 3 && uploadState.speed) return
63
uploadState.speed = bytesSent / passed
64
+ if (now - stuckSince >= 10_000) { // this will normally cause the upload to be retried after 10+10 seconds of no progress
65
+ overrideStatus = RETRY_UPLOAD // try again
66
+ abortCurrentUpload()
67
+ }
68
bytesSent = 0 // reset counter
69
bytesSentTimestamp = now
70
@@ -89,18 +95,25 @@ export async function startUpload(toUpload: ToUpload, to: string, resume=0) {
95
const splitSize = getHFS().splitUploads
96
const fullSize = toUpload.file.size
97
let offset = resume
98
+ let stopLooping = false
99
do { // at least one iteration, even for empty files
100
req = new XMLHttpRequest()
101
const finished = pendingPromise()
102
req.onloadend = () => {
103
finished.resolve()
104
if (req?.readyState !== 4) return
105
+ if (overrideStatus === RETRY_UPLOAD) {
106
+ overrideStatus = 0
107
+ stopLooping = true
108
+ startUpload(toUpload, to, offset)
109
+ return
110
+ }
111
const status = overrideStatus || req.status
112
if (!partial) // if the upload ends here, the offer for resuming must stop
113
closeLast?.()
114
if (resuming) { // resuming requested
115
resuming = false // this behavior is only for once, for cancellation of the upload that is in the background while resume is confirmed
103
- stopLooping()
116
+ stopLooping = true
117
return
118
}
119
if (!status || status === HTTP_CONFLICT) // 0 = user-aborted, HTTP_CONFLICT = skipped because existing
@@ -121,13 +134,15 @@ export async function startUpload(toUpload: ToUpload, to: string, resume=0) {
134
req.onerror = () => {
135
error(0)
136
finished.resolve()
124
- stopLooping()
137
+ stopLooping = true
138
}
139
let lastProgress = 0
140
req.upload.onprogress = (e:any) => {
141
uploadState.partial = e.loaded + offset
142
uploadState.progress = uploadState.partial / fullSize
143
bytesSent += e.loaded - lastProgress
144
+ if (e.loaded > lastProgress)
145
+ stuckSince = Date.now()
146
lastProgress = e.loaded
147
}
148
let uploadPath = getFilePath(toUpload.file)
@@ -143,9 +158,7 @@ export async function startUpload(toUpload: ToUpload, to: string, resume=0) {
158
}), true)
159
req.send(toUpload.file.slice(offset, splitSize ? offset + splitSize : undefined))
160
await finished
146
- } while (offset < fullSize)
147
-
148
- function stopLooping() { offset = fullSize }
161
+ } while (!stopLooping && offset < fullSize)
162
163
async function subscribeNotifications() {
164
if (notificationChannel) return
@@ -196,7 +209,7 @@ export async function startUpload(toUpload: ToUpload, to: string, resume=0) {
209
}
210
211
function next() {
199
- stopLooping()
212
+ stopLooping = true
213
uploadState.uploading = undefined
214
uploadState.partial = 0
215
const { qs } = uploadState