Release notes

4.0

Note

4.0 is in beta, these release notes are a work in progress

This release upgrades Tapeti to use the RabbitMQ.Client version 7, and contains major changes to the way connections and channels are handled, as described in issue #45. The aim is to improve stability and performance with while minimizing changes required to the applications using Tapeti.

Tapeti core

Breaking changes

  • Logger implementations will require changes:

    1. Methods are passed context objects instead of interfaces.

    2. A new method ConsumeStarted has been added.

    3. The ChannelType PublishDefault has been renamed to Publish.

    4. A new interface IChannelLogger has been added. Implementing it is optional but recommended.

Changes

  • Upgraded to RabbitMQ.Client version 7.
  • Refactored connection and channel handling. Channels level exceptions are handled properly and will re-create just the channel instead of the entire connection.
  • The CancellationToken passed to message handlers is now channel-specific. Running message handlers will block channel re-creation, it is therefore highly recommended to implement this in your message handlers if there is any chance they will run for more than a few seconds. See CancellationToken.
  • Introduced channel pool for publishing messages, greatly improving throughput.
  • TapetiConnectionParams now supports (case-insensitive) query parameters in the URI for:
    1. prefetchCount

    2. managementPort

    3. consumerDispatchConcurrency

    4. publishChannelPoolSize

    publishChannelPoolSize has also been added to the ConnectionStringParser.
  • Fixed the SerialTaskQueue implementation which turned out to be not entirely serial (note: no known bugs in older versions originated from this behaviour). Moved the queue to a dedicated thread to prevent congestion issues in high load scenarios.

Tapeti.Flow

The Tapeti Flow extension was designed to cache all running flows in memory, with an optional persistent backing store. To support running multiple instances of a service, this has been refactored to allow the backing implementation to determine whether or not flows are cached.

Note: flows which continue on a dynamic queue are still only stored in memory, as the dynamic queue is specific to an instance of a service. This scenario is fully supported, but not recommended, for the same reasons as the Transient extension is no longer recommended.

Tapeti.Flow.SQL

The previous implementation, where all flows are fully cached in memory, remains available as the SqlSingleInstanceCachedFlowStore. SqlMultiInstanceFlowStore has been introduced to handle multi-instance scenarios.

For an in-depth comparison and usage guide, see SQL Server.

Changes

  • WithFlowSqlRepository has been marked as obsolete. Instead WithFlowSqlStoreSingleInstanceCached or WithFlowSqlStoreMultiInstance should be called to communicate the intent and consequences.
  • Added TapetiFlowSqlMetadata helper for converting existing databases.
  • Added a ContinuationMethodMapper callback which can be used for maintaining backwards compatibility with older flows after refactoring.

3.0

Breaking changes

  • Dropped support for .NET Standard (and therefore .NET Framework 4.x). .NET 6 or higher is now required for the client.
    Note; Tapeti.Annotations continues to support .NET Standard 2.0, and as long as your Messaging packages do too you can still use Tapeti 2 on older projects and the messages published and consumed should be compatible.
  • Removed TapetiAppSettingsConnectionParams. Use TapetiConnectionParams instead using a URL or by specifying the properties manually. Alternatively you can use the ConnectionStringParser in the Tapeti.Helpers namespace. Both of these were already available in Tapeti 2, and if you used those nothing changed.
  • All middleware now uses ValueTask instead of Task.

Changes

  • ValueTask support for most methods (converge methods in Flow are the exception for now).
  • Added support for queue arguments (message TTL, maximum length, etc.).
  • Fixed #38: durable queues are verified more than once.

2.9

Tapeti.Flow

Changes

  • Parallel requests in flows can now add additional requests in an active flow by using IFlowParallelRequest
  • Added NoRequestsBehaviour parameter to ParallelRequestBuilder.Yield to simplify use cases with optional flows

2.8.2

Tapeti.Flow

  • Disabled validation of the converge method name while loading persisted flows for now, as it turned out not enough information is stored and the validation always fails

2.8.1

Tapeti core

  • Fixed NullReferenceException on shutdown when an obsolete queue is no longer present
  • Fixed PrefetchCount being incorrectly applied to the publish channel instead of the consume channel, resulting in all messages on the queue being consumed simultaniously

2.8

Tapeti.Serilog

  • Added optional WithMessageHandlerLogging middleware to output the time a message handler takes to the Serilog Logger. Includes a warning treshold and the ability to inject an IDependencyContext to add custom properties.

Repository split

  • Tapeti.Annotations, Tapeti.DataAnnotations.Extensions have been moved to their own Github repositories and are built separately. As these are rarely updated this stabilizes their version numbers which should improve compatibility for services consuming message packages from other services instead of forcing them to have the same Tapeti version.
  • Tapeti.Cmd has also been moved to it’s own Github repository as it has no dependency on the Tapeti library and vice versa.

2.7.6

Tapeti core

  • Fixed disposing non-IAsyncDisposable payloads in the message context. This could cause a response handled by Tapeti.Flow to block the consumers as the lock on a flow ID is never released.

If you are using Tapeti 2.4 or higher and are using Tapeti.Flow, upgrading to this version is highly recommended.


2.7.5

Tapeti.Transient

  • Fixed exception in Tapeti.Transient when message arrives after the timeout

2.7.1

Breaking changes

This version should be compatible for existing clients. One change requires changes to custom IExceptionStrategy implementations:

  • IExceptionStrategy.HandleException can now be async and returns a Task instead of void

2.6

Tapeti core

  • Separated publishing into separate channel and task queue to (hopefully) improve issues with acknowledgement timeouts
  • Fixed error when consuming a queue with incompatible arguments (like x-deadletter) when using EnableDeclareDurableQueues

Tapeti.Flow

  • Validate persisted flows on startup to prevent runtime errors if a continuation method is renamed
  • Fixed edge-case when receiving a flow-related message twice

Tapeti.Cmd

  • Fixed body corruption in Shovel command
  • Added DeclareQueue, RemoveQueue, BindQueue and UnbindQueue management commands

Breaking changes

This version should be compatible for existing clients. One change may require changes to custom ILogger implementations:

  • QueueExistsWarning method has been added to IBindingLogger

2.5.2

This version properly fixes the issue with body corruption since version 2.4 and the upgrade to the RabbitMQ Client 6.


2.5.1

Warning

Do not use this version

This version contains a bug introduced in version 2.4 when upgrading to the new RabbitMQ Client version 6 which can result in corruption of the message body.


2.5

Warning

Do not use this version

This version contains a bug introduced in version 2.4 when upgrading to the new RabbitMQ Client version 6 which can result in corruption of the message body.

Tapeti core

  • Implemented IAsyncDisposable on connection and subscriber
  • Added RoutingKey attribute to prefix, postfix or completely replace the routing key for messages when using the default TypeNameRoutingKeyStrategy.

A RoutingKeyHelper class has been added which can be used to add support for this attribute to custom implementations of IRoutingKeyStrategy.