Add streaming, bounded, credential-re-vending HF ingest CLI#4
Open
justinrmiller wants to merge 1 commit into
Open
Add streaming, bounded, credential-re-vending HF ingest CLI#4justinrmiller wants to merge 1 commit into
justinrmiller wants to merge 1 commit into
Conversation
A one-shot `tbl.add(staged)` of a multi-TB dataset on a `db://` enterprise connection dies after ~1h with S3 `ExpiredToken`: the table is opened once, the vended STS credentials are baked into the Lance backend, and the single long write outlives the token TTL. `ingest-hf-streaming` is the copy-pasteable client-only mitigation, with two independent levers in `core/utils/hf_streaming.py`: - Bounded sub-writes: `iter_hf_batches` streams the source into `--chunk-rows` batches so no single Lance write outlives the STS TTL. - Per-chunk re-vend: `fresh_table` returns a handle with freshly vended creds before each append. Default `connect` mode reconstructs the connection (the only lever guaranteed to re-vend); `reopen`/`latest` are documented lighter alternatives. Each chunk logs the vended `aws_session_token` prefix so a `db://` run self-verifies that credentials rotate. Two source modes: `datasets` (general, default) and `parquet` (streams parquet straight from `hf://` via HfFileSystem, scaling to datacomp-style metadata with no full download). `--resume` skips already-written rows for idempotent-ish restarts of a failed multi-TB load. The CLI is coverage-omitted like the other cluster CLIs; the bounded iterator and re-vend lever are fully unit-tested (hf_streaming.py at 100%, suite 98.99%). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A one-shot
tbl.add(staged)of a multi-TB dataset on adb://enterprise connection dies after ~1h with S3ExpiredToken. The naive flow points one Arrow dataset at the whole repo and writes it in a single Lance operation:The table is opened once, the vended STS credentials are baked into the Lance backend, and that single write can't finish inside the token's lifetime.
What
A new
ingest-hf-streamingCLI that makes the client-only mitigation copy-pasteable, matching the existingingest-imagesstyle. Two independent levers, both ingeneva_examples/core/utils/hf_streaming.py:iter_hf_batchesstreams the source into--chunk-rows-sizedRecordBatches and appends one per chunk, so no single Lance write outlives the STS TTL.fresh_tablereturns a table handle with freshly vended credentials before each append. Each chunk logs the vendedaws_session_tokenprefix so a realdb://run self-verifies that credentials rotate.Source modes:
datasets(default) —load_dataset(streaming=True)buffered into batches; works for anydatasets-streamable repo with Arrow-serializable columns.parquet— streams parquet straight fromhf://viaHfFileSystem+pyarrow.dataset(exact schema, no decode, no full download); scales to datacomp-style sharded metadata.--resumereadscount_rows()and skips already-written source rows, making a failed multi-TB load idempotent-ish on restart.The re-vend lever (design note)
The intuitive lever — re-open the table with
conn.open_table()to re-vend — could not be confirmed by static analysis.conn.open_table()does build a freshTable/_ltbl, but the actual STS vend happens inside opaque native (inner.open_table), andtbl.add()writes straight to the cached_ltblwithout refreshing. geneva's own credential-refresh primitive islatest_storage_options()(invoked only inget_reference()for remote workers, never on the local write path). The only lever guaranteed to re-vend by construction is reconstructing the connection.So
--revend-modeis pluggable, defaulting to the guaranteed option:connect(default)geneva.connectper chunk → fresh namespace client → freshdescribe_tablevend. Guaranteed to re-vend.reopenlatestlatest_storage_options()(private/internal lancedb API).Files
geneva_examples/core/utils/hf_streaming.py—iter_hf_batches,fresh_table,vended_token_prefix, and the network-bound source readers (# pragma: no cover).geneva_examples/pipeline/ingest_hf_streaming.py— the CLI.tests/test_hf_streaming.py— 21 tests (no network/cluster).pyproject.toml—ingest-hf-streamingscript entry + coverage omit (like the other cluster CLIs).README.md— "Streaming ingest" section with before/after, examples, and a full options reference..gitignore— ignorehuggingface_cache/(pre-existing gap thatingest-imagesshares viaHF_HOME).Verification
make checkgreen: ruff lint + format, 131 passed, 98.99% coverage;hf_streaming.pyat 100%.cornell-movie-review-data/rotten_tomatoes, wrote 3 chunks (20+20+10 = exactly--limit 50),table_rows 50; observed a distinctLanceNamespaceDBConnectionper chunk underconnectmode, confirming the re-vend fires.token=<none>as expected on a local dir.hf://glob → schema →to_batches, ~1.4s).Still needs a real
db://cluster (couldn't run here)token=prefix rotates across chunks under--revend-mode connect(and check whetherreopenkeeps a stable token — that would empirically confirmconnectmust remain the default).--limit.🤖 Generated with Claude Code