Added documentation for #37

This commit is contained in:
Mark van Renswoude 2021-10-29 21:07:51 +02:00
parent 8c13917f47
commit b36a3e400a
3 changed files with 48 additions and 1 deletions

View File

@ -289,3 +289,6 @@ Then install the Tapeti.Flow.SQL NuGet package and register the SqlConnectionFlo
.WithFlow()
.RegisterAllControllers()
.Build();
.. caution:: The controller and method names for response handlers and converge methods are stored in the flow and must be valid when they are loaded again. Keep that in mind if you want to refactor the code; either keep the original class and method temporarily for backwards compatibility, optionally redirecting them internally to the new code, or make sure there are no persisted flows remaining.

View File

@ -102,7 +102,10 @@ Any public method in a message controller is considered a message handler. There
- The first parameter must be the message class.
- The return type can be void, Task, Task<message class> or a message class.
The name of the method is not important to Tapeti. Any parameter other than the first will be resolved using the IoC container, although it is considered best practice to use the constructor for dependency injection instead.
The name of the method is not important to Tapeti. Any parameter other than the first will be resolved in two ways:
1. Registered middleware can alter the behaviour of parameters. Tapeti includes one by default for CancellationToken parameters, see :ref:`parameterbinding` in :doc:`indepth`.
2. Any remaining parameters are resolved using the IoC container, although it is considered best practice to use the constructor for dependency injection instead.
A new controller is instantiated for each message, so it is safe to use public or private fields to store state while handling the message. Just don't expect it to be there for the next message. If you need this behaviour, take a look at the :doc:`flow`!

View File

@ -9,6 +9,46 @@ As described in the Getting started guide, a message is a plain object which can
When communicating between services it is considered best practice to define messages in separate class library assemblies which can be referenced in other services. This establishes a public interface between services and components without binding to the implementation.
.. _parameterbinding:
Parameter binding
-----------------
Tapeti will bind the parameters of message handler methods using the registered binding middleware.
Although stated in the Getting started guide that the first parameter is always assumed to be the message class, this is in fact handled by one of the default binding middleware implementations instead of being hardcoded in Tapeti. All of the default implementations play nice and will only apply to parameters not already bound by other middleware, making it easy to extend or change the default behaviour if desired.
In addition to the message class parameter, two additional default implementations are included:
CancellationToken
^^^^^^^^^^^^^^^^^
Similar to ASP.NET, Tapeti will bind parameters of type CancellationToken to a token which is cancelled when the connection to the RabbitMQ server is closed.
.. note:: This does not indicate whether the connection was closed by the application or lost unexpectedly, either scenario will cancel the token. This is by design, as any message in-flight will be put back on the queue and redelivered anyways.
Internally this CancellationToken is called ConnectionClosed, but any name can be used. For example:
::
public async Task<CountResponseMessage> CountRabbits(CountRequestMessage message,
CancellationToken cancellationToken)
{
var count = await rabbitRepository.Count(cancellationToken);
return new CountRabbitsResponseMessage
{
Count = count
};
}
Dependency injection
^^^^^^^^^^^^^^^^^^^^
Any parameter not bound by any other means will be resolved using the IoC container which is passed to the TapetiConnection.
.. note:: It is considered best practice to use the constructor for dependency injection instead.
Enums
-----
Special care must be taken when using enums in messages. For example, you have several services consuming a message containing an enum field. Some services will have logic which depends on a specific value, others will not use that specific field at all.
@ -82,6 +122,7 @@ If all message handlers bound to a durable queue are marked as obsolete, includi
If there are still messages in the queue it's pending removal will be logged but the consumers will run as normal to empty the queue. The queue will then remain until it is checked again when the application is restarted.
Request - response
------------------
Messages can be annotated with the Request attribute to indicate that they require a response. For example: