All notable changes to the Zerobus C++ SDK are documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- JSON and protobuf streams now use a dedicated gRPC connection by default.
Set
Sdk::builder().connection_per_stream(false)to share one HTTP/2 connection across streams.
- Built on Rust SDK 2.9.0. Wrapper-facing notes for that core are in
rust/CHANGELOG.mdand https://github.com/databricks/zerobus-sdk/releases/tag/rust/v2.9.0.
- Promoted Arrow Flight ingestion to general availability across its APIs, documentation, and examples.
- Built on Rust SDK 2.8.0. Wrapper-facing notes for that core are in
rust/CHANGELOG.mdand https://github.com/databricks/zerobus-sdk/releases/tag/rust/v2.8.0.
- Fixed a use-after-free in which a custom
HeadersProvidercould be destroyed while the Rust core was still inside aget_headers()call into it during connection recovery. Provider ownership is now handed to the FFI as a heap-allocatedshared_ptrreleased by a destroy callback (detail::zerobus_cpp_headers_free) only after any in-flightget_headers()has returned; theStream/ArrowStreamno longer keeps its own providershared_ptr. Public API is unchanged —create_stream/create_arrow_streamstill take astd::shared_ptr<HeadersProvider>— and you no longer need to keep your own reference alive pastcreate_stream.
- Corrected custom-header examples and clarified that acknowledgment callbacks run once per logical ingest submission rather than once per record in a batch.
- Recovery after a flush timeout now treats unacked retrieval failure as an active stream rather than assuming the stream is terminal.
- Arrow Flight schema validation is documented at stream creation (the schema IPC
bytes passed to
create_arrow_stream), not on the first ingested batch. - Built on Rust SDK 2.7.1. Wrapper-facing notes for that core are in
rust/CHANGELOG.mdand https://github.com/databricks/zerobus-sdk/releases/tag/rust/v2.7.1.
- Correct the batch-ingest offset docs.
ingest_json_records()/ingest_proto_records()return the single logical offset assigned to the whole batch, not "the offset of the last record" — a 3-record batch on a fresh stream returns offset 0, not 2. Fixed the API docstrings, example comments, and expected-output samples.
- Fix release-bundle documentation.
cpp/README.mdwas written for a source checkout; it now covers both audiences with a "from a release bundle" build path (prebuilt-FFI CMake flags, no Rust toolchain), notes thatmake/ctestand the test suite are source-checkout only, and rewrites links that pointed outside the bundle (prerequisites, FFI, contributing, license) so they resolve from a bundle too. - Complete the proto examples' Unity Catalog metadata fetch: explain why the
dynamic-proto path needs the table schema, acquire an OAuth token from the
service-principal credentials first, and use
curl --failso an auth or permission error surfaces instead of storing an error body. - Fix the credential variable names in the
generate_filessnippet (DATABRICKS_CLIENT_ID/DATABRICKS_CLIENT_SECRET, matching the rest of the docs).
Initial release of the Zerobus C++ SDK — a RAII C++17 wrapper over the Zerobus C FFI for ingesting data into Databricks Delta tables.
- Ingest into Databricks Delta tables over a
Stream(proto and JSON record formats) or anArrowStream(Arrow Flight, Beta), with single-record and batch APIs. Streams are RAII, move-only handles over the Rust core; errors surface aszerobus::ZerobusException. Proto schemas are built at runtime from Unity Catalog table metadata viaProtoSchema::from_uc_json()(noprotocrequired). - Added an async ack callback: implement
AckCallback(or use theAckCallback::from(on_ack, on_error)lambda adapter) and register it viaStreamOptions::ack_callbackto track durability without blocking inwait_for_offset()/flush(). The callback methods arenoexcept.StreamOptions::callback_wait_policy(aCallbackWaitPolicyofuse_default()/duration(ms)/forever()) controls how longclose()drains the callback task. - Recover unacknowledged records after a failure via
Stream::get_unacked_records()/ArrowStream::get_unacked_batches(), and supply per-stream request headers with a customHeadersProvider.
- Added the C++ SDK
README.md(build, install, quickstart for JSON / proto / Arrow Flight ingestion, ingestion-format guidance, credential model, API overview,StreamOptions/ArrowStreamOptionsconfiguration tables, and an HTTP-proxy note) andCLAUDE.md(contributor guide covering the FFI boundary, RAII/memory ownership, thread-safety, and release process). AddedCONTRIBUTING.mdwith C++-specific development setup and workflow. Added C++ rows to the rootREADME.mdandCLAUDE.md, and reconciled the root Arrow-Flight andexamples/arrow/notes with the C++ SDK's0.1.0state. - Documented running the tests in
README.md: the sanitizer runs (make test SANITIZE=address/thread) and the env-var-gatedintegration_test(which variables it needs and that it skips without them). - Added runnable examples under
examples/covering all three record formats — JSON and protobuf (dynamic schema built at runtime from Unity Catalog metadata viaProtoSchema::from_uc_json, noprotocrequired), each with a single-record and a batch variant, plus Arrow Flight (Beta). Every example reads its connection settings from the environment (ZEROBUS_SERVER_ENDPOINT,DATABRICKS_WORKSPACE_URL,ZEROBUS_TABLE_NAME,DATABRICKS_CLIENT_ID,DATABRICKS_CLIENT_SECRET). They build with the SDK viaZEROBUS_BUILD_EXAMPLES(the Arrow example is skipped when Apache Arrow C++ is not installed). Includes a top-levelexamples/README.mdand per-format guides. - The examples also demonstrate advanced features inline: an async ack callback
(
StreamOptions::ack_callback) and a customHeadersProviderinexamples/json/batch.cpp, recovery of unacknowledged records (Stream::get_unacked_records()) inexamples/json/single.cpp, and Arrow IPC compression inexamples/arrow/arrow_ingest.cpp.
- Hermetic unit-test suite covering the API surface:
ZerobusException(message- retryable flag),
UnackedRecord,version(),ProtoSchema(UC-JSON round trip, error paths, move semantics), theHeadersProviderFFI trampoline (marshalling, empty/embedded-NUL/throwing guards, nulluser_data), andSdk/SdkBuilder(offline build, move, andcreate_stream/create_arrow_streamargument validation). Dependency-free and network-free; the suite also passes under AddressSanitizer.
- retryable flag),
- Added an env-var-gated live integration test (
integration_test) covering the create-stream -> ingest -> flush -> close path against a real endpoint, mirroring the Java/TypeScript integration suites. It skips (passes) unlessZEROBUS_SERVER_ENDPOINT,DATABRICKS_WORKSPACE_URL,ZEROBUS_TABLE_NAME,DATABRICKS_CLIENT_ID, andDATABRICKS_CLIENT_SECRETare set, somake testand CI stay hermetic. - Added a ThreadSanitizer CI job (
make test SANITIZE=thread) and aconcurrency_testthat exercises the documented "concurrent readers on a sharedProtoSchema" contract under many threads, catching data races the AddressSanitizer job cannot.