Repository navigation
Releases
Releases Β· rabbitmq/rabbitmq-dotnet-client
v7.3.0-beta.0
Note
7.3.0-beta.0 is a prerelease of 7.3.0. Please report problems at https://github.com/rabbitmq/rabbitmq-dotnet-client/issues.
7.3.0
User-visible behavior changes. CHANGELOG.md carries the full merged pull request and issue list.
Security
- An
amqps://URI now verifies the broker's certificate against the host name (GHSA-7xr9-fg47-hh5x). Assigning anamqps://URI toConnectionFactory.Uriaccepted a certificate issued for any host. This also affected a factory bound from configuration withSsl:Enabledset, because the reflection-based configuration binder assignsUrieven when noUrikey is present. - The name checked is
Ssl.ServerName, which assigningUrisets to the URI's host unlessServerNamealready holds a different name. A certificate that does not carry that name, as a DNS name or an IP address, now fails the handshake. That includes aHostNamechanged after theUri, which does not updateServerName. For several nodes with their own certificates, give eachAmqpTcpEndpointits ownSslOptioninstance withEnabled = trueand that node'sServerName. SettingSsl.AcceptablePolicyErrors = SslPolicyErrors.RemoteCertificateNameMismatchrestores the old behavior, and has no effect whenSsl.CertificateValidationCallbackis set. - Assigning
Urino longer discards settings made before it. It replacesSslwith a copy that keeps the certificates, callbacks, revocation check, policy and version already set, so permissive settings made before theUrinow take effect: review them. WhenSsl.Versionis not set, anamqps://URI still sets it fromAmqpUriSslProtocols.MaxInboundMessageBodySizeset before theUriis now kept rather than reset to 64 MiB. - A factory with TLS enabled no longer connects in cleartext to an endpoint without TLS (GHSA-5wrf-cc49-8x6j). Given
AmqpTcpEndpoints or anIEndpointResolver, or an assignedEndpoint, the factory used each endpoint's ownSslOption, whose TLS is off unless set, so the connection and its recoveries went unencrypted, to port 5672 when the endpoint had no port of its own. Such an endpoint now uses the factory'sSsl, including its oneServerName, and port 5671 when it has no port of its own; nodes with their own certificates need their ownSslOption, as above. An endpoint bound by the reflection-based configuration binder stores port 5672 when none is given, so give it the TLS port.IConnection.Endpointreports a copy rather than the instance passed in, and its port can differ: 5671 where the instance passed in reports 5672.ConnectionFactory.Urilikewise names port 5671 for a factory with TLS enabled and no port. A deployment that relied on the cleartext connection fails to connect after upgrading unless the broker accepts TLS on that port with a certificate forSsl.ServerName. - A connection keeps the TLS options, hosts and ports it was created with, including when it recovers. Changing an
SslOptionor an endpoint afterwards, on the factory, on an endpoint passed in or onIConnection.Endpoint, no longer reaches it; create a new connection to use different options. AnIEndpointResolver, passed in or returned byEndpointResolverFactory, is still asked for its endpoints on every recovery, and their options are read then. To follow endpoints that change while a connection is open, such as from service discovery, return them from the resolver'sAll(), not from the sequence passed toEndpointResolverFactory, which is now copied when the connection is created. - An
amqp://URI no longer turns TLS off: assigning one to a factory with TLS enabled throwsInvalidOperationException, which the reflection-based configuration binder wraps inTargetInvocationException. To connect without TLS, assignSsla newSslOptionfirst; settingSsl.Enabled = falsealso turns TLS off for any other factory or endpoint that shares that instance. - A
connection.tunewhose negotiatedframe_maxis from 1 to 4095, below the AMQP minimum, now fails the connection:CreateConnectionAsyncthrowsBrokerUnreachableExceptionwith aProtocolViolationExceptioninside (GHSA-qqh4-4hmj-6ph2). A broker, or anything between client and broker, that sent 1 to 8 broke publishing, and 1 to 7 could make it write past the end of a buffer. ARequestedFrameMaxfrom 1 to 4095 fails the same way. 0 still means no limit, and a value above about 2 GiB is now also treated as no limit instead of making every publish fail. - Field tables and arrays nested more than 32 levels deep are now rejected (GHSA-qhmm-xgrg-q669). Reading one recursed without a limit, so a
connection.startfrom the broker, or message headers set by any publisher, could overflow the stack and terminate the application. Such a value now fails the connection and every channel on it, as an unknown field type already did:CreateConnectionAsyncthrowsBrokerUnreachableException, and a delivery, abasic.returnor aBasicGetAsyncreply closes the connection with reply code 502. Deeper nesting was read before. This client now refuses to send it as well:BasicPublishAsync, or any method taking an arguments table, throwsWireFormattingExceptionbefore anything is sent, and a table that contains itself fails the same way instead of overflowing the stack. A message carrying such headers closes the connection again each time it is redelivered. From RabbitMQ 4.0, a quorum queue's default delivery limit eventually removes it; on other queues it stays until removed, for example by purging the queue, or on a stream until retention discards it. BasicGetAsyncno longer waits forever when the reply's headers cannot be read (#2076). It throws the parse error, such asSyntaxErrorException, and the connection closes with reply code 502.
Publishing a caller-owned or sequence body
Adds API and breaks implementors of IChannel (#1913, #1983):
IChannelgained four new abstract members, with no default implementations. The interface went from twoBasicPublishAsyncoverloads to six, the new ones taking anIDisposable? bodyOwneralongside either aReadOnlyMemory<byte>or aReadOnlySequence<byte>body. Any type implementingIChanneldirectly, such as a test double or a decorator, will not compile against 7.3.0 until it implements them. This is the release's only hard source break, and it affects implementors rather than callers. Five new[Obsolete]warnings also fail a warnings-as-errors build; they are listed below.- A body can now be published from a
ReadOnlySequence<byte>without being copied. Ten newIChannelExtensionsoverloads takebodyOwner, five of them for a sequence and five for aReadOnlyMemory<byte>. Ownership ofbodyOwnertransfers to the client, which disposes it once, after the message reaches the wire or when publication fails, so every segment must stay valid and unmodified until then. Passingnullis permitted but copies the body into one pooled buffer. A body that cannot be read when the client writes it closes the connection, and every channel on it (#2108). An exception from the owner'sDisposeis contained, so a failed publish still throws its own exception.
Byte slices as field table values
- A field table value, such as a message header, can now be a
ReadOnlyMemory<byte>,Memory<byte>orArraySegment<byte>(#2144). It is sent as a long string, like abyte[], and received as abyte[]. These types previously failed withWireFormattingException, whichCreateConnectionAsyncwraps inBrokerUnreachableExceptionwhen the value is inConnectionFactory.ClientProperties. - The client reads the slice each time it sends the table, so its memory must stay valid and unchanged until then. For a message header that is until the task returned by
BasicPublishAsynccompletes, which can be after the call returns. With topology recovery, exchange, queue, binding and consumer arguments are sent again on each recovery, andConnectionFactory.ClientPropertiesis sent by every connection the factory opens, so a slice in either must stay valid and unchanged until those connections are closed. - The slice is boxed in the table, so it allocates less than a copy into an exact-length
byte[]only for values longer than 8 bytes, and it takes longer to encode than abyte[].
OpenTelemetry span status and duration
Two changes visible to anyone with dashboards or alerts on this client's spans (#1978):
- Publish span duration rises by about an order of magnitude when publisher confirmations and confirmation tracking are both enabled, because the span now covers the confirmation round trip. The span also now starts before flow control, so a broker under a memory or disk alarm moves it even with confirmations off. Nothing became slower. Latency dashboards keyed on the
publishspan will move;docs/internal/opentelemetry-tracing-review.mdhas the measurements. - Failed operations now produce
Errorspans. Publisher and subscriber spans previously set no status, so a throwing consumer traced as a success, as did a nacked or returned publish on a channel with confirmations and tracking both enabled. They now setError,error.typeand an exception event, so error rates keyed on these spans go from zero to real. Cancellation the caller's own token requested is exempt and rethrows unmarked; a client-internal timeout, such asRequestedConnectionTimeout, is recorded as an error witherror.typeofBrokerUnreachableException.
OpenTelemetry tracing configuration
Now settable per factory (#2026, #2009):
- A connection's tracing configuration can be set on the factory, via
ConnectionFactory.TracingOptions, instead of only through process-wide statics. Every member of the newConnectionTracingOptionsis nullable andnullmeans inherit, resolved per member, so setting one span-shaping flag leaves whatever propag...
v7.2.2
What's Changed
- Fix URI round-trip for credentials containing special characters by @lukebakken in #1944
- Retry recovery when a topology operation times out by @ansd in #1994
New Contributors
Full Changelog: v7.2.1...v7.2.2
v7.2.1
What's Changed
- Add 'contents: read' to workflow permissions to increase the OpenSSF scorecard of the repo by @pavlofilatov1 in #1880
- Add workflow to check for GHA updates by @lukebakken in #1887
- Update GHA via
actions-upby @lukebakken in #1886 - Added TryComplete instead of comple during channel shutdown by @patriktiain in #1885
- Catch all exceptions in HeartbeatWriteTimerCallback and HeartbeatReadTimerCallback to avoid crash by @klettier in #1876
- Use dependabot to update actions refs by @lukebakken in #1896
- Bump github/codeql-action from 3 to 4 by @dependabot[bot] in #1898
- Bump actions/checkout from 6.0.1 to 6.0.2 by @dependabot[bot] in #1897
- Bump actions/cache from 5.0.2 to 5.0.3 by @dependabot[bot] in #1899
- Fix unconditional semaphore release in BasicPublishAsync when Cancell⦠by @EvheniyHlushko in #1901
- Connection recovery: remove recorded bindings of auto-delete entities by @michaelklishin in #1906
- Pre-7.2.1 release preparation by @lukebakken in #1909
New Contributors
- @pavlofilatov1 made their first contribution in #1880
- @patriktiain made their first contribution in #1885
- @klettier made their first contribution in #1876
- @dependabot[bot] made their first contribution in #1898
- @EvheniyHlushko made their first contribution in #1901
Full Changelog: v7.2.0...v7.2.1
v7.2.0
What's Changed
- Ensure that disposable instances are always disposed. by @lukebakken in #1814
- Ship OAuth2 client version 2 by @lukebakken in #1824
- Add dedicated exception for
basic.returnmessages. by @lukebakken in #1832 - Pin .NET SDK versions for CI/CD runs by @danielmarbach in #1842
- Prevent downstream dependencies to pickup MinVer as a depencency by @romerod in #1838
- Cancel recovery CTS on connection Dispose by @AndreReise in #1839
- Improve AsyncManualResetEvent implementation to address races by @danielmarbach in #1843
- Allow parent/child relationship in Opentelemetry spans by @meum in #1779
- Investigate & fix
SemaphoreFullExceptionby @lukebakken in #1819 - fix: prevent possible connection leak in AutorecoveringConnection during creation by @krisz2000 in #1857
- Closes#1849: include a message id tag in rabbitmqactivitysource for published messages by @YayBurritos in #1852
- Bump versions by @lukebakken in #1872
- Do not handle publisher confirms when disposed by @lukebakken in #1873
- Ensure Connection and Channel cancellation token properly float into handlers by @danielmarbach in #1740
- Added option to specify ClientCertificateContext in .NET 8+ by @tyb-dev in #1866
- Prepare PublicAPI for next release by @lukebakken in #1874
- v7.2.0 CHANGELOG by @lukebakken in #1875
New Contributors
- @romerod made their first contribution in #1838
- @AndreReise made their first contribution in #1839
- @meum made their first contribution in #1779
- @krisz2000 made their first contribution in #1857
- @YayBurritos made their first contribution in #1852
Full Changelog: v7.1.2...v7.2.0
v7.1.2
What's Changed
- Serialize sequence number as
longby @lukebakken in #1806 - Skip flaky test by @lukebakken in #1810
- Address
ObjectDisposedExceptionby @lukebakken in #1809
Full Changelog: v7.1.1...v7.1.2
v7.1.1
What's Changed
- Fix bug in
IntervalListby @lukebakken in #1785 - Demonstrate handling of
Channel.Closeby @lukebakken in #1791 - Port
IntAllocatorfromrabbitmq-java-clientby @lukebakken in #1790 - Fix handling when rate limit lease can't be acquired. by @lukebakken in #1794
Full Changelog: v7.1.0...v7.1.1
v7.1.0
What's Changed
- chore: bump regular System.Text.RegularExpressions due to a known CVE in earlier versions by @aygalinc in #1735
- Simplify preprocessor directives by @danielmarbach in #1741
- Address flaky integration tests by @lukebakken in #1742
- Toxiproxy manager change by @lukebakken in #1744
- Set TestTfmsInParallel to false for Integration tests by @lukebakken in #1745
- More updates for the current OTel (OpenTelemetry) conventions by @iinuwa in #1717
- Update NuGet packages by @lukebakken in #1748
- Update copyright year to 2025 by @lukebakken in #1755
- Ensure broker-originated channel closure completes by @lukebakken in #1764
- Remove whitespaces from csproj files by @sungam3r in #1768
- Misc items by @lukebakken in #1766
- Fix typos by @sungam3r in #1770
- Handle
OperationCanceledExceptionin RPC continuations by @lukebakken in #1753 - Allow setting heartbeat timeout to
TimeSpan.Zeroby @lukebakken in #1773 - Create cancellation token from
timeoutby @lukebakken in #1775 - Track down
ObjectDisposedExceptionsby @lukebakken in #1772 - Fix very rare deadlock by @lukebakken in #1771
- Fix #1777 by @lukebakken in #1781
- Fix rare deadlock, second try by @lukebakken in #1782
New Contributors
Full Changelog: v7.0.0...v7.1.0
v7.1.0-alpha.1
What's Changed
- chore: bump regular System.Text.RegularExpressions due to a known CVE in earlier versions by @aygalinc in #1735
- Simplify preprocessor directives by @danielmarbach in #1741
- Address flaky integration tests by @lukebakken in #1742
- Toxiproxy manager change by @lukebakken in #1744
- Set TestTfmsInParallel to false for Integration tests by @lukebakken in #1745
- More updates for the current OTel (OpenTelemetry) conventions by @iinuwa in #1717
- Update NuGet packages by @lukebakken in #1748
- Update copyright year to 2025 by @lukebakken in #1755
- Ensure broker-originated channel closure completes by @lukebakken in #1764
- Remove whitespaces from csproj files by @sungam3r in #1768
- Misc items by @lukebakken in #1766
- Fix typos by @sungam3r in #1770
- Handle
OperationCanceledExceptionin RPC continuations by @lukebakken in #1753 - Allow setting heartbeat timeout to
TimeSpan.Zeroby @lukebakken in #1773 - Create cancellation token from
timeoutby @lukebakken in #1775 - Track down
ObjectDisposedExceptionsby @lukebakken in #1772 - Fix very rare deadlock by @lukebakken in #1771
- Fix #1777 by @lukebakken in #1781
New Contributors
Full Changelog: v7.0.0...v7.1.0-alpha.1
v7.1.0-alpha.0
What's Changed
- chore: bump regular System.Text.RegularExpressions due to a known CVE in earlier versions by @aygalinc in #1735
- Simplify preprocessor directives by @danielmarbach in #1741
- Address flaky integration tests by @lukebakken in #1742
- Toxiproxy manager change by @lukebakken in #1744
- Set TestTfmsInParallel to false for Integration tests by @lukebakken in #1745
- More updates for the current OTel (OpenTelemetry) conventions by @iinuwa in #1717
- Update NuGet packages by @lukebakken in #1748
- Update copyright year to 2025 by @lukebakken in #1755
- Ensure broker-originated channel closure completes by @lukebakken in #1764
- Remove whitespaces from csproj files by @sungam3r in #1768
- Misc items by @lukebakken in #1766
- Fix typos by @sungam3r in #1770
- Handle
OperationCanceledExceptionin RPC continuations by @lukebakken in #1753
New Contributors
Full Changelog: v7.0.0...v7.1.0-alpha.0
v7.0.0
GitHub milestone for RabbitMQ.Client version 7.0.0
What's Changed
- Fall back to rabbitmqctl (or rabbitmqctl.bat) if RABBITMQ_RABBITMQCTL_PATH or umbrella path are not available by @michaelklishin in #818
- Switch to Verify for API approval test by @bording in #820
- AutorecoveringConnection uses ContinuationTimeout from ConnectionFactory by @AndrzejKrol in #823
- Do not throw on invalid ReplyTo address by @ig-sinicyn in #828
- Introduce PublicationAddress.TryParse and switch BasicProperties.ReplyToAddress to use it by @michaelklishin in #831
- Throw ObjectDisposedException when required by @lukebakken in #832
- Restore Constants class as public by @lukebakken in #833
- Move Constants to RabbitMQ.Client by @lukebakken in #834
- Replacing usage of ManualResetEvent with ManualResetEventSlim by @stebet in #837
- Optimizing memory usage even further. by @stebet in #824
- Using a linked list for fast efficient tracking of [publisher confirm] delivery tags by @stebet in #836
- Adding System.Threading.Channels for simplified, better performing code. by @stebet in #835
- Using interpolated strings for better code readability. by @stebet in #840
- getting rid of a Func allocation by @bollhals in #841
- Making sure AsyncEventHandlers are all run. Fixes issue #838. by @stebet in #839
- simplify WriteShortstr by @bollhals in #845
- Deletion of unreachable code by @Pliner in #847
- Deletion of unused UseBackgroundThreadsForIO by @Pliner in #846
- eliminate allocations from InboundFrame by @bollhals in #848
- Frame optimizations by @stebet in #844
- Delete AutoClose from SessionManager by @Pliner in #852
- Fixing rethrown exceptions to properly preserve stackframes. by @stebet in #850
- throw ArgumentOutOfRangeException when table key is too long (> 255) by @bollhals in #849
- Adding BinaryPrimitives support for NETSTANDARD targets by @stebet in #851
- Minor improvements and optimizations by @bollhals in #842
- simplify missed heartbeat recognition by @bollhals in #854
- remove task yield by @bollhals in #855
- Fix RabbitMQ version parsing by @lukebakken in #862
- Report a Uri scheme of "amqps" in AmqpTcpEndpoint.ToString() iff SslOption is enabled in #864
- Re-merge pull request #855 from bollhals/remove.task.yield by @lukebakken in #863
- Prep for 6.1.1 by @lukebakken in #870
- Fix AppVeyor build by @lukebakken in #871
- Move BinaryTableValue to public section by @BenBorn in #880
- Ability to do concurrent dispatches both on the async as well as the sync consumer by @danielmarbach in #866
- Refactor: extracted RabbitMQ node management functions from IntegrationFixture by @pergh in #884
- Switch WorkPool of ConsumerWorkService to channels by @danielmarbach in #882
- use cached empty BasicProperties when null by @bollhals in #887
- add size hint variable for PublishBatch creation by @bollhals in #888
- fix issue 868 by @bollhals in #878
- Implement BasicPublishBatch with ReadOnlyMemory by @danielmarbach in #865
- 7.x: remove deprecated message publishing method overloads by @danielmarbach in #895
- precompute sizes and and simplify BasicProperties presence by @bollhals in #890
- Edit docs by @JeremyMahieu in #896
- Do DNS resolution before connection attempt by @JeremyMahieu in #893
- Unify on IModel by @danielmarbach in #858
- Missing ConfigureAwait in TcpClientAdapter by @danielmarbach in #897
- Pull ProcessingConcurrency into connection factory interface by @danielmarbach in #899
- Getting rid of Command allocations by @bollhals in #902
- Rename ProcessingConcurrency to ConsumerDispatchConcurrency by @danielmarbach in #905
- More descriptive exception in WriteShortstr by @tmasternak in #908
- Reduce work allocations by @bollhals in #910
- cache the frameHeaderBuffer & rentedArray by @bollhals in #911
- simplify ack/nack handling by @bollhals in #912
- Switch to Mozilla Public License 2.0 (MPL 2.0) by @dcorbacho in #916
- reduce the amount of times we rent / return from arraypool by @bollhals in #919
- Running Tests docs: quotes for setting env vars in windows by @JeremyMahieu in #921
- Typo in Extension class name by @JeremyMahieu in #922
- remove APIGen project by @bollhals in #924
- Command Id instead of class & method id by @bollhals in #925
- change AmqpVersion to struct by @bollhals in #927
- change from Memory to ReadOnlyMemory by @bollhals in #928
- Update dependencies to latest versions by @lukebakken in #929
- Code cleanups by @stebet in #931
- Add FxCop with only ConfigureAwait rule enabled for now by @danielmarbach in #932
- Expose events ConsumerTagChangeAfterRecovery and QueueNameChangeAfterRecovery by @paulomf in #935
- Remove IAsyncConnectionFactory by @danielmarbach in #933
- Use span directly instead of reader / writer for methods & properties by @bollhals in #936
- Switch FxCop to PrivateAssets="All" by @danielmarbach in #941
- Breaking public API change: fold IAutorecoveringConnection [back] into IConnection by @michaelklishin in #943
- Make sure OnCallbackException is executed for AsyncConsumers by @BarShavit in #946
- Replace Travis with GitHub Actions by @asbjornu in #952
- Minor improvements to GitHub Actions CI build. by @stebet in #954
- Update IModel Documentation by @JKamsker in #958
- 7.0: update target framework from net461 to netcoreapp3.1 by @bollhals in #971
- Speeding up shortstr/longstr (de)serialization. by @stebet in #985
- Cleaning up and adding more benchmarks. by @stebet in #983
- Speeding up decimal (de)serialization. by @stebet in #984
- some more wire formatting improvements by @bollhals in #989
- 8.0: imple...