Skip to content

Resume a dropped mesh download where it stopped, without counting it as a failed attempt - #1799

Merged
Robbie1977 merged 3 commits into
masterfrom
development
Sep 22, 2026
Merged

Robbie1977 merged 3 commits into
masterfrom
development

Conversation

@Robbie1977

Copy link
Copy Markdown
Contributor

A mesh body that broke off part-way was retried from the top, and after four such drops handed to the server fallback - which fetches the same URL over a worse channel. For a user on a weak or long path (the mobile/continent skew in the GA breakdown) that is the wrong response to an ordinary interruption.

Client VFBv2.4.5.10:

  • fetchWithRetry counts two kinds of failure apart. A request that got nowhere (refused, HTTP error, body dead before a new byte) is a strike; four strikes end the call as before. A body that dropped after making progress is not a strike: the download resumes from the last byte parsed with Range: bytes=N-, and the strike count resets. RESUMES (8, window.VFB_FETCH_RESUMES) bounds how many interruptions one call rides out. An HTTP error on a resume keeps the offset.
  • createObjConsumer() keeps the parser and decoder across requests, so a resumed body is more chunks to the same parse. A 206 is spliced in only if it is the same version of the file (strong ETag where both responses show one, else Last-Modified) and its Content-Range starts exactly at the parse position (or, where that header is hidden, its Content-Length pins the start). A 200 restarts the parse; any other 206 is refused. Both silent-corruption cases - a partial body parsed as a whole file, a whole file fed into a half-fed parser - are tested.
  • No If-Range: it made the browser preflight with OPTIONS, which the data hosts answer 405, so no resume ever left the page. The version check above replaces it.
  • attempts is now every request the load made; resumes is new alongside it. 16 new tests (61 total).

This repo: client pin bumped; geomfail/georecover carry :rN when any request was a resume (absent otherwise, so existing names are unchanged).

Verified on v2-dev against real data hosts: a 9.6 MB mesh cut at 200 KB on cayenne resumed on buttermilk with a 206 at the right offset and matching ETag, reported georecover:obj:jrchjrcj:a2:r1, and the resulting mesh has exactly the file's vertex and face counts. Needs Access-Control-Expose-Headers: ETag, Content-Range, Accept-Ranges on the data hosts for the strong validator (now set in HAProxy); falls back to Last-Modified and Content-Length without it.

The client now resumes a mesh download that dropped part-way (HTTP
Range from the last byte parsed, conditioned on the file's ETag) and
does not count such an interruption as a failed attempt. geomfail and
georecover carry an rN part when any request of the load was a resume;
absent otherwise, so the existing names are unchanged. aN is now every
request the load made.
The resume falls back to Last-Modified and Content-Length, which a
cross-origin response always lets the page read; on v2-dev the ETag and
Content-Range it looked for first were hidden and it started over.
A resume sends Range alone and checks the version of what comes back
itself; If-Range made the browser preflight, which the data hosts
refuse, so on v2-dev no resume ever got out.
@Robbie1977
Robbie1977 merged commit cb2c4f6 into master Sep 22, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant