Skip to content

[SEND] Chunked/resumable upload so a stalled PUT does not discard the whole object #913

Description

@mzeier

Context (root-cause fix — larger, scope first)

Send splits a file client-side into separate single-PUT objects (no S3 multipart, per thunderbird/platform-infrastructure#274). Each object is one PUT with no resume: a stall at 28s on a 100MB PUT throws away the entire 100MB and restarts from zero. Over a long-haul path (the Sentry report SEND-SUITE-FRONTEND-24H is a Costa Rica user → B2 eu-central-003) this is the underlying mechanism behind retry exhaustion. Timeout/retry tuning (#1, #3) papers over this; resumable upload attacks it directly.

Where

  • packages/send/frontend/src/lib/upload.tsdoUpload (L110), batch loop + Promise.all (L299-317)
  • packages/send/frontend/src/lib/filesync.tssendBlob (L132)
  • packages/send/frontend/src/lib/helpers.tsuploadWithTracker (L267)

Change (design + spike before implementation)

Implement chunked/resumable upload within an object so a transient stall resumes from the last successful chunk instead of restarting the whole object. Evaluate options:

  • S3 multipart upload (B2 is S3-compatible) with per-part retry, or
  • Application-level chunking with a resume manifest.
    Produce a short design note first (storage cost, B2 multipart compatibility, encryption-boundary implications) before coding.

Do NOT

  • Do not reduce BATCH_SIZE (currently 5) at upload.ts:~304. Bench Phase B (5×100MB concurrent) passed 150/150 with zero retries — concurrency is not implicated; serial uploads are where failures appeared.

Acceptance criteria

  • Design note attached covering multipart vs app-level chunking, B2 compatibility, encryption boundaries, storage/cost impact
  • A transient mid-upload stall resumes without re-sending already-uploaded bytes
  • Large-file (100MB+) upload reliability validated against B2 eu-central-003

Refs

Metadata

Metadata

Assignees

No one assigned

    Labels

    SendThis is an issue with Thunderbird Send's backend/frontend components

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions