Skip to content

fix(eventhubs): enforce the AMQP link maximum on single event sends - #5113

Draft
Johnathan W (j7nw4r) wants to merge 2 commits into
Azure:mainfrom
j7nw4r:j7nw4r/fix-eventhubs-send-event-size-check
Draft

fix(eventhubs): enforce the AMQP link maximum on single event sends#5113
Johnathan W (j7nw4r) wants to merge 2 commits into
Azure:mainfrom
j7nw4r:j7nw4r/fix-eventhubs-send-event-size-check

Conversation

@j7nw4r

@j7nw4r Johnathan W (j7nw4r) commented Aug 20, 2026

Copy link
Copy Markdown
Member

Summary

ProducerClient::send_event and ProducerClient::send_message now reject a message larger than the maximum the sender link reports, and they do not transfer it. The batch path already enforced that limit, so the two publish paths now agree.

Motivation

A live run against a Standard namespace read the link maximum as 1048576 bytes, and a 2 MiB event sent with send_event returned Ok(()) and reached the partition. The AMQP library is the cause: fe2o3-amqp treats max-message-size as a split boundary and fragments an oversized payload across transfer frames instead of refusing it, and its newest release still does, so the client must make the check itself. A caller that publishes one event at a time got no size protection from the client, and the .NET client refuses the same publication.

Changes

  • Added the public ErrorKind::MessageSizeExceeded { requested, max_allowed } variant. ErrorKind is #[non_exhaustive], so the addition is additive. ErrorKind::InvalidBatchSize was not reused, because it reports a batch size option the caller asked for and its text does not describe an oversized message. The .NET client keeps the two faults apart for the same reason.
  • Added ProducerClient::check_message_size, the one crate-internal function that holds the comparison.
  • send_message reads the maximum from RecoverableSender::max_message_size, the same lookup create_batch uses, and checks the encoded message before the transfer. send_event reaches the check through send_message.
  • A link that reports no maximum is not checked, because AMQP 1.0 section 2.7.3 gives an unset or zero max-message-size the meaning "no limit". This differs on purpose from create_batch, which treats a missing maximum as an error.
  • The boundary is inclusive, so a message of exactly the maximum is still sent.
  • The two paths share the limit source and the comparison, not the arithmetic. The batch path adds an envelope, pads each message, and compares a running total against a cap the caller can lower, and a single send has none of those.
  • Added the CHANGELOG entries and the rustdoc for both public methods.

Test plan

  • Four offline unit tests drive check_message_size for a size above the maximum, exactly at it, below it, and with no reported maximum. They failed to compile before the fix, and each one fails on its own under a matching mutation of the comparison.
  • One live test, send_event_rejects_message_above_link_maximum, sends a 2 MiB event through both public methods, asserts the error kind, then sends a normal event on the same client to show the link is still up. The live run is PENDING, because one shared namespace served eight concurrent runs; a serialized live pass follows.
  • cargo test -p azure_messaging_eventhubs --all-features --lib: 148 passed, 0 failed, 14 ignored.
  • RUSTFLAGS=-Dwarnings cargo test --no-run --package azure_messaging_eventhubs: exit 0.
  • cargo fmt --check, cargo clippy --all-features --all-targets --no-deps -- -Dwarnings, and RUSTDOCFLAGS=-Dwarnings cargo doc --no-deps --all-features: all exit 0.

Closes #5101

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
3 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

Issue Azure#5101 reports that `send_event` accepts an event larger than the
sender link allows. The AMQP library splits the oversized payload across
transfer frames instead of refusing it, so the event reaches the
partition and the caller gets no size protection. These tests pin the
refusal before any fix exists.

Four offline unit tests drive `ProducerClient::check_message_size`. They
pin the refusal above the link maximum, the inclusive boundary at the
maximum, the unchanged behavior below it, and the skip when the link
reports no maximum. AMQP 1.0 section 2.7.3 gives an unset maximum the
meaning "no limit", so the send path must not invent one.

One live test sends a 2 MiB event through both `send_event` and
`send_message`, asserts the error kind, then sends a small event on the
same client to show the link is still up.

The tests fail to compile against the unchanged source, because neither
`check_message_size` nor `ErrorKind::MessageSizeExceeded` exists yet.
`send_event` and `send_message` did not compare the encoded message
against the maximum the sender link reports. fe2o3-amqp treats that
maximum as a split boundary: it fragments an oversized payload across
transfer frames with `more = true` instead of refusing it, so a 2 MiB
event reached the partition. The behavior is the same in 0.17.0, so an
upgrade does not help and this client must make the check itself.

`send_message` now reads the link maximum, encodes the message, and
refuses it when the encoded size is larger. The boundary is inclusive,
so a message of exactly the maximum is still sent. A link that reports
no maximum is not checked, because AMQP 1.0 gives an unset or zero
`max-message-size` the meaning "no limit". The batch path already
enforced the same limit and does not change.

The new `ErrorKind::MessageSizeExceeded { requested, max_allowed }`
variant lets a caller branch on the kind instead of the message. It
mirrors the `EventHubsException` with `FailureReason.MessageSizeExceeded`
that .NET reports for the same message.

Fixes Azure#5101
@minghuaw

Copy link
Copy Markdown

This is likely a bug in fe2o3, opened an issue, but the fix will likely need a breaking release

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Event Hubs] send_event does not enforce the AMQP link maximum that batches enforce

2 participants