You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -2956,9 +2956,7 @@ NOTE: If you use Hibernate Reactive, look at <<writing-entities-managed-by-hiber
2956
2956
2957
2957
Because we write to a database, we must run this method in a transaction.
2958
2958
Yet, sending the entity to Kafka happens asynchronously.
2959
-
The operation returns a `CompletionStage` (or a `Uni` if you use a `MutinyEmitter`) reporting when the operation completes.
2960
-
We must be sure that the transaction is still running until the object is written.
2961
-
Otherwise, you may access the object outside the transaction, which is not allowed.
2959
+
We can achieve this by using `.sendAndAwait()` or `.sendAndForget()` on the `MutinyEmitter`, or `.send().toCompletableFuture().join()` on the `Emitter`.
2962
2960
2963
2961
To implement this process, you need the following approach:
public CompletionStage<Void> storeAndSendToKafka(Fruit fruit) { // <2>
2983
+
@Transactional // <1>
2984
+
public void storeAndSendToKafka(Fruit fruit) { // <2>
2987
2985
fruit.persist();
2988
-
return emitter.send(new FruitDto(fruit)); // <3>
2986
+
emitter.sendAndAwait(new FruitDto(fruit)); // <3>
2989
2987
}
2990
2988
}
2991
2989
----
2992
2990
<1> As we are writing to the database, make sure we run inside a transaction
2993
-
<2> The method receives the fruit instance to persist. It returns a `CompletionStage` which is used for the transaction demarcation. The transaction is committed when the return `CompletionStage` completes. In our case, it's when the message is written to Kafka.
2991
+
<2> The method receives the fruit instance to persist.
2994
2992
<3> Wrap the managed entity inside a Data transfer object and send it to Kafka.
2995
2993
This makes sure that managed entity is not impacted by the Kafka serialization.
2994
+
Then await the completion of the operation before returning.
2995
+
2996
+
NOTE: You should not return a `CompletionStage` or `Uni` when using `@Transactional`, as all transaction commits will happen on a single thread, which impacts performance.
<1> Inject the Hibernate Reactive `SessionFactory`.
3205
-
<2> Capture the caller Vert.x context.
3206
-
<3> Begin a Hibernate Reactive transaction.
3207
-
<4> Begin a Kafka transaction.
3208
-
<5> Persist the payload and send the entity to Kafka.
3209
-
<6> The Kafka transaction terminates on the Kafka producer sender thread.
3210
-
We need to switch to the Vert.x context previously captured in order to terminate the Hibernate Reactive transaction on the same context we started it.
3204
+
<2> Begin a Hibernate Reactive transaction.
3205
+
<3> Begin a Kafka transaction.
3206
+
<4> Persist the payload and send the entity to Kafka.
3207
+
3208
+
Alternatively, you can use the `@WithTransaction` annotation to start a transaction and commit it when the method returns:
Copy file name to clipboardExpand all lines: _versions/main/guides/messaging.adoc
+74Lines changed: 74 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -356,6 +356,80 @@ public class MyProfileBean {
356
356
}
357
357
----
358
358
359
+
==== Pausable Channels
360
+
361
+
Injected `@Channel` streams are not subscribed to by default, so the flow of messages is controlled by the application code using reactive streams and Mutiny APIs.
362
+
But for `@Incoming` methods, the flow of messages is controlled by the runtime.
363
+
364
+
Pausable channels provide a mechanism to control message flow programmatically.
365
+
This is useful in scenarios where producers or consumers need to stop temporarily due to managing the lifecycle or performing maintenance operations.
366
+
367
+
To use pausable channels, you need to activate it with the configuration property `pausable` set to `true`.
368
+
369
+
[source, properties]
370
+
----
371
+
mp.messaging.incoming.my-channel.pausable=true
372
+
# optional, by default the channel is NOT paused initially
If a channel is configured to be pausable, you can get the `PausableChannel` by channel name from the `ChannelRegistry` programmatically, and pause or resume the channel as needed:
0 commit comments