Skip to content

RepositoryExportReader

Class: warmhub.RepositoryExportReader

RepositoryExportReader()

Verifies one logical export, across one or more transport segments.

Row lines are hashed as they are consumed and each segment’s trailer is checked against that segment’s digest, so a tampered row fails on the line that follows the last one, not on a second pass over a buffered file. A second digest runs the length of the export and never resets, and that one is the caller’s whole-stream receipt.

restart()

Discard everything and return to the pre-first-byte state.

Resuming is not always on offer. An export redeemed from a token arrives as one presigned object download, and a transfer that dies halfway has no cursor to continue from — the only recovery is to fetch the object again from the top. begin_segment is the wrong tool there: it deliberately preserves the rolling digest, the record count and after_durable_id, which is exactly the state a fresh download must not carry. Equivalent to constructing a new reader, and used so that a caller already holding this one keeps a live handle. The reader is left open on a fresh first segment, so feeding may begin immediately without a begin_segment of its own.

begin_segment()

Start a new transport segment.

The first segment opens with the header. A resumed one does not: the client asked for afterDurableId, so the server replies with rows and a trailer for that segment alone. “Resumed” is derived from after_durable_id rather than passed in, because that is the exact condition under which the request carried the parameter.

feed(chunk: bytes)

Consume some bytes of the current segment, yielding whole rows.

Chunk-at-a-time rather than iterable-at-a-time because the async transport hands bytes over an async for, and both adapters must drive the same state machine rather than two copies of it.

end_segment()

Close the current segment, keeping the digest for the next one.

read_segment(chunks: Iterable[bytes])

Consume one transport segment, yielding its validated rows.

A segment that ends without a trailer is not an error here — that is the resumable case, and after_durable_id is the key to continue from. Call finish when no further segment is coming.

finish()

The final segment’s trailer, or raise because it never arrived.

A segment that ends with a trailer is the whole remainder the server meant to send, so a trailer is also the end of the export.

header

The header, once the first line of the first segment is read.

trailer

The final segment’s verified trailer, or None while incomplete.

A trailer describes the segment that carried it, not the export: a resumed segment’s recordCount and contentSha256 cover only the rows that segment sent, because the server cannot know how much the client already holds. record_count and content_sha256 are the whole-stream figures.

record_count

Rows consumed so far, across every segment.

content_sha256

The rolling digest of every row line read so far, across segments.

This is the whole-stream integrity value. No trailer claims it once an export has been resumed, so it is the client’s own receipt: hash it again from the rows you stored and the two must agree.

after_durable_id

Resume key: the durable identity of the last row already verified.

is_complete

Documentation is not yet available.