batchcorder
A Rust-backed Python library for caching Arrow record-batch streams so they can be replayed multiple times from a source that can only be read once.
The problem
Arrow RecordBatchReader is a single-use stream — once consumed, it is gone.
Training loops and multi-pass data pipelines need to iterate the same stream
repeatedly without re-reading from disk or the network each time.
What batchcorder does
StreamCache wraps any Arrow stream source (anything that implements
__arrow_c_stream__) and stores each RecordBatch in a cache. Two storage
modes are supported:
- Memory-only (default): batches are stored as reference-counted pointers in RAM; reads are zero-copy and no IPC serialisation happens.
- Hybrid memory+disk: batches are serialised to an append-only IPC file on disk; a configurable hot layer keeps recently ingested batches in RAM to reduce disk I/O.
Multiple independent readers can replay the stream concurrently, each maintaining their own position in the batch sequence.
flowchart LR
U["upstream source<br/>(read once)"] --> D["StreamCache<br/>[mem cache / mem+disk cache]"]
D --> R0["StreamCacheReader 0<br/>(from batch 0)"]
D --> R1["StreamCacheReader 1<br/>(from batch 0)"]
D --> R2["StreamCacheReader 2<br/>(from batch 3)"]
Installation
pip install batchcorder
Usage
import tempfile
import pyarrow as pa
from batchcorder import StreamCache
table = pa.table({"x": [1, 2, 3], "y": [4, 5, 6]})
# Memory-only (default capacity = total physical RAM)
ds = StreamCache(table.to_reader(max_chunksize=1))
# Memory-only with explicit capacity
ds = StreamCache(
table.to_reader(max_chunksize=1),
memory_capacity=64 * 1024 * 1024, # 64 MB
)
# Hybrid memory+disk
tmp = tempfile.mkdtemp()
ds = StreamCache(
table.to_reader(max_chunksize=1),
memory_capacity=64 * 1024 * 1024, # 64 MB in RAM
disk_path=tmp,
disk_capacity=512 * 1024 * 1024, # 512 MB on disk
)
# Replay as many times as needed
for batch in ds:
print(batch)
# Or get an independent reader handle
reader = ds.reader()
result = pa.RecordBatchReader.from_stream(reader).read_all()
# Bounded-memory: evict batches once all readers have passed them
ds = StreamCache(
table.to_reader(max_chunksize=1),
max_readers=2, # at most 2 reads; batches evicted when both advance
)
# Pre-ingest everything upfront
ds.ingest_all()
Compatibility
StreamCache and StreamCacheReader implement both __arrow_c_stream__
and __arrow_c_schema__, so they work with any Arrow-compatible library:
import pyarrow as pa
import duckdb
pa.table(ds) # PyArrow
pa.table(ds.reader()) # via StreamCacheReader
duckdb.table("ds") # DuckDB
Key properties
- Single-read source: the upstream stream is consumed exactly once; all subsequent reads come from the cache.
- Concurrent readers: multiple
StreamCacheReaderinstances from the same stream cache are fully independent and thread-safe. - Lazy ingestion: batches are fetched from the upstream source on demand as readers advance, not upfront.
- Replay from any position:
ds.reader(from_start=True)(default) replays from batch 0;ds.reader(from_start=False)starts from the current ingestion frontier (next batch not yet ingested). - Bounded-memory streaming: set
max_readers=Nto evict batches once allNreaders exist and have advanced past them — eviction does not begin until allNreaders have been created.max_readersis a hard cap on total readers ever created (dropping a reader does not free a slot). Once eviction has started,reader(from_start=True)raisesValueError. When unset, all batches are retained indefinitely.
Development
# Install dependencies and build the extension
uv sync --no-install-project --dev
uv run maturin develop --uv
# Run tests
uv run pytest
# Run all pre-commit checks
uv run pre-commit run --all-files
Metadata
Release files for batchcorder 0.1.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| batchcorder-0.1.3.tar.gz | 245.4 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| batchcorder-0.1.3-cp310-abi3-win_amd64.whl | CPython 3.10 | abi3 | Windows x86-64 | Details |
| batchcorder-0.1.3-cp310-abi3-win32.whl | CPython 3.10 | abi3 | Windows x86-32 | Details |
| batchcorder-0.1.3-cp310-abi3-manylinux_2_28_aarch64.whl | CPython 3.10 | abi3 | Linux glibc 2.28+ ARM64 | Details |
| batchcorder-0.1.3-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ x86-64 | Details |
| batchcorder-0.1.3-cp310-abi3-macosx_11_0_arm64.whl | CPython 3.10 | abi3 | macOS 11.0+ ARM64 | Details |
| batchcorder-0.1.3-cp310-abi3-macosx_10_12_x86_64.whl | CPython 3.10 | abi3 | macOS 10.12+ x86-64 | Details |
Total release size: 7.2 MB
Release files / batchcorder-0.1.3.tar.gz
| Download URL | batchcorder-0.1.3.tar.gz |
|---|---|
| Size | 245.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bd74b90c83d146bf1bbf4582c1e7e04b312fe17df8bf1b034c0ba90532bf2b14
|
|
BLAKE2b-256 checksum How to use checksums |
114def6ee4f348b31736c34dc81c327052a61e77f31fe1bf862ccb28364d4410
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.13.3
|
Release files / batchcorder-0.1.3-cp310-abi3-win_amd64.whl
| Download URL | batchcorder-0.1.3-cp310-abi3-win_amd64.whl |
|---|---|
| Size | 1.0 MB |
| Tags | CPython 3.10 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
90c8a5155020213bcda2e5a9d533a429aee04cde4ec5cd032da932b8341d83f2
|
|
BLAKE2b-256 checksum How to use checksums |
68ae36b740b070a756d31ada6d46636918fab3aa0f89b809ccdde32a773ae2c9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.13.3
|
Release files / batchcorder-0.1.3-cp310-abi3-win32.whl
| Download URL | batchcorder-0.1.3-cp310-abi3-win32.whl |
|---|---|
| Size | 891.9 kB |
| Tags | CPython 3.10 Windows x86-32 abi3 |
|
SHA-256 checksum How to use checksums |
47c5a1846f9e28cc6d1d6ec802525d64244e9df7f6a2f396b9ece8ee66b690f3
|
|
BLAKE2b-256 checksum How to use checksums |
a5fd66e46d2a6e82e074abd03b49d53ff6b55acd2c2b634733beea86aa2a8d4d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.13.3
|
Release files / batchcorder-0.1.3-cp310-abi3-manylinux_2_28_aarch64.whl
| Download URL | batchcorder-0.1.3-cp310-abi3-manylinux_2_28_aarch64.whl |
|---|---|
| Size | 1.3 MB |
| Tags | CPython 3.10 Linux glibc 2.28+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
24a3825c707149851bc2271a93a3873842bb282f1fc031c41a022c38ed8c857a
|
|
BLAKE2b-256 checksum How to use checksums |
c34fe92d207da271016428f2dbb4bae1d23e5d6ffb2f4120131ef69d8bbdda7c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.13.3
|
Release files / batchcorder-0.1.3-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | batchcorder-0.1.3-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 1.4 MB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
703d2ac6e1409e4c199ad71042600b4e27a658847883fe173dbfd65e7a5fff49
|
|
BLAKE2b-256 checksum How to use checksums |
aee15049542d85de2ec3753655e11224a9fa0422eb135228670886d5eb9ab339
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.13.3
|
Release files / batchcorder-0.1.3-cp310-abi3-macosx_11_0_arm64.whl
| Download URL | batchcorder-0.1.3-cp310-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 1.1 MB |
| Tags | CPython 3.10 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
024f07f8daa8f5fe00eb577abd8e80baecb5a74374579df68194ac3eff77ea29
|
|
BLAKE2b-256 checksum How to use checksums |
e2a5ecafe8a525d507d2b49ee612da2cf119832674cb535318f2092d033935cc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.13.3
|
Release files / batchcorder-0.1.3-cp310-abi3-macosx_10_12_x86_64.whl
| Download URL | batchcorder-0.1.3-cp310-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 1.2 MB |
| Tags | CPython 3.10 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
8971845bb2b92e318d19d39b373e13b40c1fa98b0eeed37b8aee63a59ce7c975
|
|
BLAKE2b-256 checksum How to use checksums |
768bf13bb954e848b868e8a3bfa9116bfa7cbf541e665c3575852815757e5fe6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.13.3
|