feat(client): Add streaming batch (many) API to Python client#419
Draft
feat(client): Add streaming batch (many) API to Python client#419
Conversation
Introduces `session.many()` for executing multiple get/put/delete operations with automatic batching and streaming end-to-end — no buffering of request or response bodies. - New `many.py`: `Put`, `Get`, `Delete` operation types, `ManyResponse` result, and `execute_many()` orchestrator. Small puts are batched via multipart; puts over 1 MB or with `IO[bytes]` bodies go individually. Concurrent execution via `ThreadPoolExecutor` with configurable concurrency (default 3, matching Rust client semantics). - New `multipart.py`: custom multipart encoder (lazy `Iterator[bytes]`, supports per-part custom headers and `IO[bytes]` bodies) and streaming decoder (`iter_multipart_response`) that parses parts incrementally across arbitrary-sized chunks without buffering the full response. - `client.py`: exposes `Session.many()` and re-exports operation types and `ManyResponse` from the top-level package.
Semver Impact of This PR🟡 Minor (new features) 📋 Changelog PreviewThis is how your changes will appear in the changelog. New Features ✨
🤖 This preview updates automatically when you update the PR. |
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.
Adds
session.many()to the Python client for executing multiple get/put/delete operations in batches, with a fully streaming request/response pipeline.The batch protocol uses multipart/form-data with per-part custom headers (
x-sn-batch-operation-kind,x-sn-batch-operation-key, etc.). No existing Python library supports both streaming encoding with arbitrary per-part headers and streaming decoding, so both are implemented inmultipart.py.Streaming pipeline (no buffering):
_build_batch_parts(generator) →encode_multipart(yieldsbyteslazily) → urllib3 chunked transfer encodingresponse.stream(65536)→iter_multipart_response(incremental boundary detection across arbitrary chunks) →_parse_batch_response(generator) → caller receivesIterator[ManyResponse]Operation classification:
bytesPut bodies: compressed eagerly (required for size-based batching), then classified — ≤1 MB goes in a batch request, >1 MB goes individually via the standard PUT endpointIO[bytes]Put bodies: always sent individually to avoid eager readingConcurrency:
ThreadPoolExecutordispatches batch chunks and individual ops concurrently (defaultconcurrency=3). Results arrive in completion order, matching the Rust client'sbuffer_unorderedsemantics. Sequential execution (concurrency=1) preserves input order.