GH-654 Update routing and RSocket routing documentation with details on 'MessageRoutingCallback'
Resolves #654
This commit is contained in:
@@ -142,7 +142,47 @@ public class RoutingFunction implements Function<Object, Object> {
|
||||
. . .
|
||||
}
|
||||
----
|
||||
The routing instructions could be communicated in several ways;
|
||||
The routing instructions could be communicated in several ways. We support providing instructions via Message headers, System
|
||||
properties as well as pluggable strategy. So let's look at some of the details
|
||||
|
||||
*MessageRoutingCallback*
|
||||
|
||||
The `MessageRoutingCallback` is a strategy to assist with determining the name of the route-to function definition.
|
||||
|
||||
[source, java]
|
||||
----
|
||||
public interface MessageRoutingCallback {
|
||||
|
||||
/**
|
||||
* Determines the name of the function definition to route incoming {@link Message}.
|
||||
*
|
||||
* @param message instance of incoming {@link Message}
|
||||
* @return the name of the route-to function definition
|
||||
*/
|
||||
String functionDefinition(Message<?> message);
|
||||
}
|
||||
----
|
||||
|
||||
All you need to do is implement it and and register it as a bean. The framework will automatically
|
||||
pick it up and use it for routing decisions.
|
||||
For example
|
||||
|
||||
[source, java]
|
||||
----
|
||||
@Bean
|
||||
public MessageRoutingCallback customRouter() {
|
||||
return new MessageRoutingCallback() {
|
||||
@Override
|
||||
public String functionDefinition(Message<?> message) {
|
||||
return (String) message.getHeaders().get("func_name");
|
||||
}
|
||||
};
|
||||
}
|
||||
----
|
||||
|
||||
In the preceding example you can see a very simple implementation of `MessageRoutingCallback` which determines the function definition from
|
||||
`func_name` header of the incoming Message.
|
||||
|
||||
|
||||
*Message Headers*
|
||||
|
||||
@@ -170,8 +210,26 @@ or `spring.cloud.function.routing-expression` as application properties. The rul
|
||||
previous section apply here as well. The only difference is you provide these instructions as
|
||||
application properties (e.g., `--spring.cloud.function.definition=foo`).
|
||||
|
||||
NOTE: It is important to understand that providing `spring.cloud.function.definition`
|
||||
or `spring.cloud.function.routing-expression` as Message headers will only work for imperative functions (e.g., `Function<Foo, Bar>`).
|
||||
That is to say that we can _only_ route ***per-message*** with imperative functions. With reactive functions we can not route
|
||||
***per-message***. Therefore you can only provide your routing instructions as Application Properties.
|
||||
It's all about unit-of-work. In imperative function unit of work is Message so we can route based on such unit-of-work.
|
||||
With reactive function unit-of-work is the entire stream, so we'll act only on the instruction provided via application
|
||||
properties and route the entire stream.
|
||||
|
||||
*Order of priority for routing instructions*
|
||||
|
||||
Given that we have several mechanisms of providing routing instructions it is important to understand the priorities for
|
||||
conflict resolutions in the event multiple mechanisms are used at the same time, so here is the order:
|
||||
|
||||
1. `MessageRoutingCallback` (If function is imperative will take over regardless if anything else is defined)
|
||||
2. Message Headers (If function is imperative and no `MessageRoutingCallback` provided)
|
||||
3. Application Properties (Any function)
|
||||
|
||||
|
||||
*Function Filtering*
|
||||
Filtering is the type of routing where there are only tow paths - 'go' or 'discard'. In terms of functions it mean
|
||||
Filtering is the type of routing where there are only two paths - 'go' or 'discard'. In terms of functions it mean
|
||||
you only want to invoke a certain function if some condition returns 'true', otherwise you want to discard input.
|
||||
However, when it comes to discarding input there are many interpretation of what it could mean in the context of your application.
|
||||
For example, you may want to log it, or you may want to maintain the counter of discarded messages. you may also want to do nothing at all.
|
||||
|
||||
@@ -55,19 +55,22 @@ rsocketRequesterBuilder.tcp("localhost", port)
|
||||
.subscribe(System.out::println);
|
||||
```
|
||||
|
||||
### Function Definitions
|
||||
### Order of priority for routing instructions
|
||||
|
||||
As you can see from the preceding example, we provide function definition as a value to `route(..)` operator of `RSocketRequester.Builder`.
|
||||
However that is not the only way. You can also use standard `spring.cloud.function.definition` property as well as `spring.cloud.function.routing-expression` property.
|
||||
However that is not the only way. You can also use standard `spring.cloud.function.definition` property as well as `spring.cloud.function.routing-expression` or property or `MessageRoutingCallback` on the server side of the RSocket interaction (see "Function Routing and Filtering" section of reference manual).
|
||||
This raises a question of _order_ and _priorities_ when it comes to reconsiling a conflict in the event several ways of providing definition are used. So it is a mater of clearly stating the rule whcih is:
|
||||
|
||||
***1 - spring.cloud.function.routing-expression***
|
||||
The `spring.cloud.function.routing-expression` property takes precedence over all other ways of providing definition. So, in the event you may have also use `route(..)` operator or `spring.cloud.function.definition` property, they will be ignored if `spring.cloud.function.routing-expression` property is provided.
|
||||
***1 - MessageRoutingCallback***
|
||||
The `MessageRoutingCallback` takes precedence over all other ways of providing function definition resolution.
|
||||
|
||||
***2 - route(..)***
|
||||
***2 - spring.cloud.function.routing-expression***
|
||||
The `spring.cloud.function.routing-expression` property takes next precedence. So, in the event you may have also use `route(..)` operator or `spring.cloud.function.definition` property, they will be ignored if `spring.cloud.function.routing-expression` property is provided.
|
||||
|
||||
***3 - route(..)***
|
||||
The next in line is `route(..)` operator. So in the event there are no `spring.cloud.function.routing-expression` property but you defined `spring.cloud.function.definition` property, it will be ignored in favor of definition provided by the `route(..)` operator.
|
||||
|
||||
***3 - spring.cloud.function.definition***
|
||||
***4 - spring.cloud.function.definition***
|
||||
The `spring.cloud.function.definition` property is the last in the list allowing you to simply `route("")` to empty string.
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user