Multi is SmallRye Mutiny’s type for an asynchronous stream of zero or more items. A stream may keep producing items indefinitely; when it ends, it emits a completion event. Use Multi where one result is not enough—for example, for streamed gRPC messages or multiple results from reactive data access. Uni represents a single asynchronous result instead. section 4.8.1 section 7.7 section 8.2.2
A Multi becomes useful when its pipeline is subscribed to. Fluent stages run as items arrive: they can transform items, observe them without changing them, or filter them out. Subscription starts the pipeline; constructing it alone does not. Completion can have its own callback. section 8.2.2
Transform and filter a stream
Create a Multi from "a", "b", and "c"; uppercase each item, append " item", and filter out the result beginning with "B". The subscriber receives "A item" and "C item", followed by the completion callback. Intermediate observation still sees all three uppercase items. section 8.2.2
Listing 8.1 An example use of the Mutiny API
Multi.createFrom().items("a", "b", "c")
.onItem()
.transform(String::toUpperCase)
.onItem()
.invoke(s -> System.out.println("Intermediate stage " + s))
.onItem()
.transform(s -> s + " item")
.filter(s -> !s.startsWith("B"))
.onCompletion()
.invoke(() -> System.out.println("Stream completed"))
.subscribe()
.with(s -> System.out.println("Subscriber received " + s));
The listing shows how transform, invoke, filter, completion, and subscription fit into one fluent Multi pipeline. section 8.2.2
For bidirectional gRPC streaming, mark both request and response messages with `stream` in the protobuf method. The generated reactive service can then accept `Multi<InsertCarRequest>` and return `Multi<CarResponse>`. Each incoming request is mapped to a car, persisted, and mapped to a response, allowing multiple cars to be added over one connection. section 4.8.1 section 8.4.2
A reactive return type does not make every operation nonblocking. The inventory implementation uses blocking database I/O, so its gRPC method needs `@Blocking` rather than execution on an event-loop thread. Hibernate Reactive and reactive drivers provide a nonblocking data-access alternative. section 8.4.2 section 7.7
Multi can also connect reactive-messaging methods. A producer emits ticks as `Multi<Long>`; a processor maps them to a `Multi<String>` on another channel; a consumer prints the resulting messages. section 9.3.2
