Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add section about the execution model in reactive guides #19640

Merged
merged 1 commit into from
Aug 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions docs/src/main/asciidoc/amqp-reference.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,52 @@ mp.messaging.incoming.people-out.link-name=people

More details about the AMQP Address model can be found in the https://activemq.apache.org/components/artemis/documentation/2.0.0/address-model.html[Artemis documentation].

[#blocking-processing]
=== Execution model and Blocking processing

Reactive Messaging invokes your method on an I/O thread.
See the xref:quarkus-reactive-architecture.adoc[Quarkus Reactive Architecture documentation] for further details on this topic.
But, you often need to combine Reactive Messaging with blocking processing such as database interactions.
For this, you need to use the `@Blocking` annotation indicating that the processing is _blocking_ and should not be run on the caller thread.

For example, The following code illustrates how you can store incoming payloads to a database using Hibernate with Panache:

[source,java]
----
import io.smallrye.reactive.messaging.annotations.Blocking;
import org.eclipse.microprofile.reactive.messaging.Incoming;

import javax.enterprise.context.ApplicationScoped;
import javax.transaction.Transactional;

@ApplicationScoped
public class PriceStorage {

@Incoming("prices")
@Blocking
@Transactional
public void store(int priceInUsd) {
Price price = new Price();
price.value = priceInUsd;
price.persist();
}

}
----

[NOTE]
====
There are 2 `@Blocking` annotations:

1. `io.smallrye.reactive.messaging.annotations.Blocking`
2. `io.smallrye.common.annotation.Blocking`

They have the same effect.
Thus, you can use both.
The first one provides more fine-grained tuning such as the worker pool to use and whether it preserves the order.
The second one, used also with other reactive features of Quarkus, uses the default worker pool and preserves the order.
====

== Customizing the underlying AMQP client

The connector uses the Vert.x AMQP client underneath.
Expand Down
13 changes: 12 additions & 1 deletion docs/src/main/asciidoc/kafka.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,12 @@ Injecting `@Channel("prices")` or having `@Incoming("prices")` does not automati
You need to configure an inbound connector with `mp.messaging.incoming.prices\...` or have an `@Outgoing("prices")` method somewhere in your application (in which case, `prices` will be an in-memory channel).
====

[#blocking-processing]
=== Blocking processing

You often need to combine Reactive Messaging with blocking processing such as database interactions.
Reactive Messaging invokes your method on an I/O thread.
See the xref:quarkus-reactive-architecture.adoc[Quarkus Reactive Architecture documentation] for further details on this topic.
But, you often need to combine Reactive Messaging with blocking processing such as database interactions.
For this, you need to use the `@Blocking` annotation indicating that the processing is _blocking_ and should not be run on the caller thread.

For example, The following code illustrates how you can store incoming payloads to a database using Hibernate with Panache:
Expand Down Expand Up @@ -1550,6 +1553,14 @@ You can enable this by adding the `quarkus-kubernetes-service-binding` extension

When running in appropriately configured Kubernetes clusters, Kafka extension will pull its Kafka broker connection configuration from the service binding available inside the cluster, without the need for user configuration.

== Execution model

Reactive Messaging invokes user's methods on an I/O thread.
Thus, by default, the methods must not block.
As described in <<blocking-processing>>, you need to add the `@Blocking` annotation on the method if this method will block the caller thread.

See the xref:quarkus-reactive-architecture.adoc[Quarkus Reactive Architecture documentation] for further details on this topic.

[[kafka-configuration]]
== Configuration Reference

Expand Down
8 changes: 8 additions & 0 deletions docs/src/main/asciidoc/mailer-reference.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,14 @@ Otherwise, search for the template as the specified location. In this particular
<3> Set the data used in the template.
<4> `MailTemplate.send()` triggers the rendering and, once finished, sends the e-mail via a `Mailer` instance.

[[execution-model]]
== Execution model

The reactive mailer is non-blocking, and the results are provided on an I/O thread.
See the xref:quarkus-reactive-architecture.adoc[Quarkus Reactive Architecture documentation] for further details on this topic.

The non-reactive mailer blocks until the messages are sent to the SMTP server.
Note that does not mean that the message is delivered, just that it's been sent successfully to the SMTP server, which will be responsible for the delivery.

[[testing]]
== Testing email sending
Expand Down
1 change: 1 addition & 0 deletions docs/src/main/asciidoc/reactive-event-bus.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ void consumeBlocking(String message) {
----

When using `@Blocking`, it ignores the value of the `blocking` attribute of `@ConsumeEvent`.
See the xref:quarkus-reactive-architecture.adoc[Quarkus Reactive Architecture documentation] for further details on this topic.
====

Asynchronous processing is also possible by returning either an `io.smallrye.mutiny.Uni` or a `java.util.concurrent.CompletionStage`:
Expand Down
5 changes: 4 additions & 1 deletion docs/src/main/asciidoc/reactive-routes.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,15 @@ The code presented in this guide is available in this {quickstarts-base-url}[Git

Before going further, let's have a look at the HTTP layer of Quarkus.
Quarkus HTTP support is based on a non-blocking and reactive engine (Eclipse Vert.x and Netty).
All the HTTP requests your application receive are handled by _event loops_ (IO Thread) and then are routed towards the code that manages the request.
All the HTTP requests your application receive are handled by _event loops_ (I/O Thread) and then are routed towards the code that manages the request.
Depending on the destination, it can invoke the code managing the request on a worker thread (Servlet, Jax-RS) or use the IO Thread (reactive route).
Note that because of this, a reactive route must be non-blocking or explicitly declare its blocking nature (which would result by being called on a worker thread).

image:http-architecture.png[alt=Quarkus HTTP Architecture]

See the xref:quarkus-reactive-architecture.adoc[Quarkus Reactive Architecture documentation] for further details on this topic.


== Declaring reactive routes

The first way to use reactive routes is to use the `@Route` annotation.
Expand Down