1

I'm running a Quarkus Kafka producer inside a lambda. The thing is, that I want to block the main thread until all messages have been produced (and acknowledged) until I terminate the lambda execution. I see, that I can normally use the CompletionStage<Void> send(T msg); of the microprofile Emitter, however, it only accepts a payload and not a Message, which I need to send the Metadata of the outgoing Kafka messages. Could you think of a way around that?

iliev951
  • 33
  • 4

1 Answers1

0

You can add acknowledgement and negative-acknowledgement functions to a Message, within which you can complete a future. Then, that future can be waited for after sending the message.

@Inject
@Channel("example-channel")
@OnOverflow(value = OnOverflow.Strategy.THROW_EXCEPTION)
Emitter<ObjectToSend> objectEmitter;

@Blocking
public void emitNewObject(ObjectToSend objectToSend) {
    try {
        CompletableFuture<Void> future = new CompletableFuture<>();

        Message<ObjectToSend> message = buildMessage(objectToSend, future);
        objectEmitter.send(message);

        future.get();
    } catch (InterruptedException | ExecutionException e) {
        log.error("Error sending message", e);
        throw new RuntimeException(e);
    }
}

private Message<ObjectToSend> buildMessage(ObjectToSend objectToSend, CompletableFuture<Void> future) {
    return Message.of(objectToSend)
        .withAck(() -> {
            future.complete(null);
            return CompletableFuture.completedFuture(null);
        }).withNack(reason -> {
            future.completeExceptionally(reason);
            return CompletableFuture.completedFuture(null);
        });
}

In fact, the implementation of the emitter for the method that you mention in the question, does the same thing.

peterhuba
  • 68
  • 1
  • 7