Skip to content

[Rust] Add Avro record format (avro feature) - #827

Merged
irinatomic-db merged 2 commits into
mainfrom
irina-tomic_data/avro/rust-core
Sep 10, 2026
Merged

irinatomic-db merged 2 commits into
mainfrom
irina-tomic_data/avro/rust-core

Conversation

@irinatomic-db

@irinatomic-db irinatomic-db commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

PR stack

What changes are proposed in this pull request?

Adds the Avro record format to the Rust SDK, behind the off-by-default avro feature (Beta). Ephemeral streams only; server support is pending. Default builds are unchanged.

Declare the writer schema at stream creation with .avro(schema_json), then ingest either a record object the stream encodes against the schema (AvroRecord(AvroValue)) or a pre-encoded datum (AvroBytes) — both via the existing ingest_record_offset / ingest_records_offset. AvroValue is apache_avro::types::Value (re-exported); it can represent every Avro type, so the record path is exhaustive.

Implementation notes:

  • apache-avro is an optional dep, pulled only by the avro feature. It requires Rust 1.85; default builds are unaffected.
  • Ingest accepts impl Into<PreparedInput> (a #[doc(hidden)] payload type). A blanket From<T: Into<EncodedRecord>> keeps every existing caller unchanged; AvroRecord carries an un-encoded AvroValue.
  • The writer schema is parsed once at build() and stored in TableProperties next to the JSON wire form, so it's reused on ingest and survives stream recovery.
  • CI compiles, lints, and tests the feature via --features avro steps in ci-rust.yml (the default --workspace / make lint runs don't touch it).

How is this tested?

cd rust

# With the feature (unit + doctests incl. AvroRecord/AvroBytes cases)
cargo test  -p databricks-zerobus-ingest-sdk --features avro
cargo clippy -p databricks-zerobus-ingest-sdk --features avro --all-targets

# Default (feature off) — no regressions
cargo test -p databricks-zerobus-ingest-sdk

# Whole workspace builds/tests (ffi/jni not broken)
cargo build --workspace
cargo test  --workspace --no-run

cargo fmt --all --check

# Excluded example builds standalone
cd examples/avro && cargo build --examples

danilonajkov-db
danilonajkov-db previously approved these changes Sep 4, 2026
Comment thread rust/.gitignore
target/
.cargo/
# examples/avro is a non-workspace crate; its lockfile is not tracked.
examples/avro/Cargo.lock

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

weird that we need this

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 on the weird

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a side effect of examples/avro being temporarily excluded from the workspace: the excluded crate builds its own lockfile that we don't track. It goes away once avro is ungated and the crate rejoins members (the root lock takes over). Added a comment explaining it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We actually probably shouldn't ever "ungate" Avro the same way we didn't "ungate" Arrow. The features flag isn't necessarily for gating a feature, but instead just lets users not pull in parts of the binary they are not interested in. Ideally we would have done this for more parts of the SDK.

Comment thread rust/examples/avro/src/main.rs Outdated
Comment thread rust/Cargo.toml Outdated
Comment on lines 12 to 15
# Excluded: as a member it would force the sdk `avro` feature across the workspace
# and break ffi/jni. Build it standalone with `cargo build` inside examples/avro.
exclude = ["examples/avro"]
resolver = "2"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do we resolve this problem for other features?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I clarified the comment.

  • The avro feature is permanent (never ungated) - it just lets users who don't need Avro skip apache-avro and its Rust 1.85 floor.
  • The workspace exclusion (and this untracked lockfile) is the genuinely temporary part. ffi/jni currently build the sdk without avro and match EncodedRecord/EncodedBatch exhaustively, so making examples/avro a member would unify avro onto them and break those matches (EncodedRecord::Avro(_) not covered).

It goes away when ffi/jni gain Avro support (#830): they'll enable avro on the sdk dependency just like they already do for arrow-flight, add the match arms, and examples/avro rejoins members - at which point this lockfile is tracked like any other.

Comment thread rust/sdk/src/builder/stream_builder.rs Outdated
Comment thread rust/sdk/src/builder/stream_builder.rs Outdated
Comment thread rust/sdk/src/stream/grpc/connection.rs Outdated
Comment thread rust/sdk/src/stream_configuration.rs Outdated
Comment thread rust/sdk/src/stream/grpc/supervisor.rs Outdated
Comment thread rust/examples/avro/README.md Outdated
Comment thread rust/sdk/src/stream/grpc/connection.rs Outdated
Comment thread rust/sdk/src/stream_configuration.rs Outdated
Comment thread rust/sdk/src/stream/grpc/ingest.rs Outdated
@irinatomic-db
irinatomic-db force-pushed the irina-tomic_data/avro/rust-core branch from 9df57f6 to 8ecc3b6 Compare September 8, 2026 10:07
Comment thread rust/sdk/src/stream/grpc/ingest.rs Outdated
Comment thread rust/sdk/src/lib.rs Outdated
Comment thread rust/sdk/src/stream/grpc/mod.rs Outdated
Comment thread rust/sdk/Cargo.toml
Comment thread rust/sdk/src/record_types.rs Outdated
Comment thread rust/sdk/src/stream/grpc/ingest.rs Outdated

@teodordelibasic-db teodordelibasic-db left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this is planned for a future PR, but cargo test --workspace and make lint (clippy --all) use default features. Every Avro unit test is #[cfg(feature = "avro")]. rust/tests/Cargo.toml enables arrow-flight but not avro. examples/avro is excluded from the workspace, so it has no CI step either. The green checks do not compile this feature.

Comment thread rust/examples/avro/src/main.rs Outdated
@irinatomic-db
irinatomic-db force-pushed the irina-tomic_data/avro/rust-core branch 2 times, most recently from 629fe96 to b3f71e4 Compare September 9, 2026 11:36
Comment thread rust/sdk/src/builder/stream_builder.rs Outdated
@irinatomic-db
irinatomic-db force-pushed the irina-tomic_data/avro/rust-core branch from b3f71e4 to dc78f50 Compare September 9, 2026 11:44

@teodordelibasic-db teodordelibasic-db left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

StreamConfigurationOptions.record_type still lists Proto/Json/Unspecified only.

@teodordelibasic-db teodordelibasic-db left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's also fix ingest_record / ingest_records in multiplexed_stream.rs as they still take Into<EncodedRecord>.

pub async fn ingest_record(
    &self,
    payload: impl Into<PreparedInput>,
) -> ZerobusResult<MessageId> {
    self.check_closed()?;
    let idx = self.pick_substream();
    let stream = &self.streams[idx];
    let encoded_batch = stream.prepare_record(payload)?;
    self.enqueue_reserved(stream, idx, encoded_batch).await
}

Comment thread rust/sdk/src/stream/grpc/ingest.rs Outdated
Comment thread rust/sdk/src/stream/grpc/ingest.rs Outdated
Comment thread rust/sdk/src/lib.rs
Comment thread rust/sdk/src/builder/stream_builder.rs Outdated
Comment thread rust/NEXT_CHANGELOG.md
@irinatomic-db
irinatomic-db force-pushed the irina-tomic_data/avro/rust-core branch from f7363a9 to ad00f87 Compare September 9, 2026 15:37
Comment thread .github/workflows/ci-rust.yml Outdated
Comment thread rust/README.md Outdated
Comment thread rust/README.md Outdated

@teodordelibasic-db teodordelibasic-db left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM once the remaining three comments are addressed and we double check CI. We should also probably not link internal Google Docs in the PR description, but no harm done I guess. Feel free to ping for reapproval.

@irinatomic-db

irinatomic-db commented Sep 10, 2026

Copy link
Copy Markdown
Contributor Author

@teodordelibasic-db

I've rebased onto main and removed my step from the CI job. The avro tests are running as part of the CI since you've added the --all-features arg. Also cleaned up the README and fixed the examples to encode the record with apache_avro instead of hand-written bytes.

@irinatomic-db
irinatomic-db force-pushed the irina-tomic_data/avro/rust-core branch from da1e5d9 to 1ca178c Compare September 10, 2026 12:27

@teodordelibasic-db teodordelibasic-db left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@irinatomic-db
irinatomic-db force-pushed the irina-tomic_data/avro/rust-core branch from 1ca178c to 41d38b9 Compare September 10, 2026 13:02
Signed-off-by: Irina Tomic <irina.tomic@databricks.com>
Signed-off-by: Irina Tomic <irina.tomic@databricks.com>
@irinatomic-db
irinatomic-db force-pushed the irina-tomic_data/avro/rust-core branch from 41d38b9 to 7e0e733 Compare September 10, 2026 13:09
@irinatomic-db
irinatomic-db added this pull request to the merge queue Sep 10, 2026
Merged via the queue into main with commit d483741 Sep 10, 2026
50 checks passed
@irinatomic-db
irinatomic-db deleted the irina-tomic_data/avro/rust-core branch September 10, 2026 13:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants