Skip to content

Stream installation exports instead of assembling the archive in memory #47

Description

@TusanHomichi

Problem or outcome

record_export::export_at (#46) reads every finalized version of the scope with fetch_all and then assembles the ZIP archive in a Vec<u8> before the HTTP handler returns it as one body. For the installation scope this holds the corpus in memory while the export is produced. #46 already releases each version's bytes as they are written (rows are consumed by build_archive), so the peak is roughly one copy of the exported bytes plus one row rather than two copies, but a very large finalized history still costs memory in proportion, and the process can be pressured before the download completes.

The outcome is an installation export whose memory use is bounded by a few units, not by the history: rows are read incrementally and the archive is written to the response as it is produced, with the same documented bytes.

Scope

In scope:

  • Stream the query (a cursor over evaluation_version in archive order) into a ZIP writer that writes to the response body as it goes, for every scope or for the installation scope alone.
  • Keep the format byte-identical for a given scope and export instant (docs/formats/record-export.md): stored entries, fixed entry order and metadata, canonical manifests. Note that a non-seekable writer emits data descriptors, which the format document must either permit explicitly or the implementation must avoid (for example by computing sizes and CRCs first, since stored entries have known lengths).
  • Decide how a failure part-way through a streamed body is surfaced to the operator (a truncated ZIP does not verify, which is the right failure, but the interface should say what happened).
  • Update ADR 0014's cost note once exports stream.

Out of scope:

Acceptance criteria

  • An installation export with many finalized versions completes with memory bounded by a few units, measured and stated in the PR.
  • The streamed archive is byte-identical to the buffered one for the same scope and instant, proven by a test that produces both.
  • export verify accepts the streamed archive, and the format document says exactly what changed in the container, if anything.
  • A mid-stream failure is visible to the operator and never presented as a complete export.

Expected proof

  • cargo test --workspace with a test producing a large invented corpus and comparing streamed and buffered bytes.
  • The usual gates: cargo fmt --check, cargo clippy --workspace --all-targets -- -D warnings, web/ check and build if the interface changes.

Related roadmap, decisions, or issues

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions