up2k: re-hs if unknown-wark or chunk-exists;

previous behavior:

* when a chunk already existed on the server, it would
   unstitch and continue retrying each individual chunk

* upon unknown-wark (file already completed), it would
   upload the remaining scheduled chunks before bailing

the unknown-wark behavior was accidental bullshit

the chunk-exists behavior was intentional, assumed optimal for
preserving tcp window-scaling, just not when running behind a
bufferbloating reverseproxy which may disconnect the client on
a timeout before the response is delivered, and "some clients"
still follow rfc2616-8.2.4 (retries the POST, wtf...)
wasting bandwidth + maybe further worsening conditions

"some clients" is specifically firefox with the devtools not open

another firefox joke is that it doesn't read the server-response
if the server does not drain the request-body; we end up in
xhr.onerror with no idea why, must assume the worst

new behavior:

in both scenarios, drop all scheduled chunks to be uploaded and
redo handshake, to as far as possible avoid retransmissions;
firefox will still eagerly retry 4 times but whatever

u2c was/is fine; nothing to be done

depending on network conditions and physical distance, this MAY
result in lower total speed, but the average case is likely a
net-positive, wasting less bandwidth on retransmissions,
in exchange for resetting tcp window-scaling
This commit is contained in:
ed 2026-08-03 20:08:19 +00:00
parent 2c6497b644
commit c0c638c917

View file

@ -998,6 +998,14 @@ function up2k_init(subtle) {
});
}
function unqueue_up(t) {
t.postlist = [];
var arr = st.todo.upload;
for (var a = arr.length - 1; a >= 0; a--)
if (arr[a].nfile == t.n)
arr.splice(a, 1);
}
var pvis = new U2pvis("bz", '#u2cards', uc, st),
donut = new Donut(uc, st);
@ -2631,7 +2639,7 @@ function up2k_init(subtle) {
cbd.push(a == cdr_idx ? cdr_sz : chunksize);
}
t.postlist = [];
unqueue_up(t);
t.wark = response.wark;
var missing = response.hash;
for (var a = 0; a < missing.length; a++) {
@ -2920,8 +2928,7 @@ function up2k_init(subtle) {
var txt = unpre((xhr.response && xhr.response.err) || xhr.responseText);
if (txt.indexOf('upload blocked by x') + 1) {
apop(st.busy.upload, upt);
for (var a = pcar; a <= pcdr; a++)
apop(t.postlist, a);
unqueue_up(t);
pvis.seth(t.n, 1, "ERROR");
pvis.seth(t.n, 2, txt.split(/\n/)[0]);
pvis.move(t.n, 'ng');
@ -2944,8 +2951,10 @@ function up2k_init(subtle) {
st.etac.u++;
st.etac.t++;
}
else if (txt.indexOf('already got that') + 1 ||
txt.indexOf('already being written') + 1) {
else if (txt.indexOf('already got that') + 1) {
unqueue_up(t);
}
else if (txt.indexOf('already being written') + 1) {
t.nojoin = t.nojoin || t.postlist.length;
console.log("ignoring dupe-segment with backoff", t.nojoin, t.name, t);
if (!toast.visible && st.todo.upload.length < 4)
@ -2953,6 +2962,10 @@ function up2k_init(subtle) {
}
else {
xhrchk(xhr, L.u_cuerr2.format(snpart, Math.ceil(t.size / chunksize), esc(t.name)), "404, target folder not found (???)", "warn", t);
if (txt.indexOf('unknown wark') == 0) {
t.cooldown = t.coolmul = 0;
unqueue_up(t);
}
chill(t);
}
orz2(xhr);
@ -2963,8 +2976,10 @@ function up2k_init(subtle) {
apop(t.postlist, a);
if (!t.postlist.length) {
t.t_uploaded = Date.now();
pvis.seth(t.n, 1, 'verifying');
st.todo.handshake.unshift(t);
if (!has(st.busy.handshake, t)) {
pvis.seth(t.n, 1, 'verifying');
st.todo.handshake.unshift(t);
}
}
tasker();
}
@ -2999,6 +3014,7 @@ function up2k_init(subtle) {
if (!toast.visible)
toast.warn(9.98, L.u_cuerr.format(snpart, Math.ceil(t.size / chunksize), esc(t.name)), t);
unqueue_up(t); // maybe unknown wark (ff drops undrained rsp)
t.nojoin = t.nojoin || t.postlist.length; // maybe rproxy postsize limit
console.log('chunkpit onerror,', t.name, t);
orz2(xhr);