Correct way to detach a computation and forward context with Reactor

Viewed 291

In a Spring Boot project, I sometimes need to "fire and forget" a time-consuming task from within an already non-blocking context, and to forward the current subscriber Context to it.

I have an implementation that works but I feel it may be overcomplicated or not recommended. Here is what I'm doing:

    static Mono<Object> longTask() {
        return Mono.deferContextual(ctx ->
            Mono.delay(Duration.ofMillis(500))
                .doOnSuccess(ignored -> System.out.println("print 2nd: " + ctx.get("x")))
        );
    }

    // Improve me
    static Mono<Object> fireAndForgetLongTask() {
        return Mono.deferContextual(ctx -> {
            longTask()
                .contextWrite(ctx)
                .subscribeOn(Schedulers.single())
                .subscribe();
            System.out.println("print 1st");
            return Mono.empty();
        });
    }

    // Hypothetical caller
    public static void main(String[] args) {
        fireAndForgetLongTask()
            .contextWrite(Context.of("x", "42"))
            .then(Mono.delay(Duration.ofMillis(1000)))
            .block();
    }

Is it correct to call .subscribe() from inside Mono.deferContextual()? Is there a simpler way to write fireAndForgetLongTask()?

Reading the documentation, I was under the impression that I could just do this:

    static Mono<Object> fireAndForgetLongTask() {
        return longTask()
            .subscribeOn(Schedulers.single())
            .doOnSuccess(ignored -> System.out.println("print 1st"));
    }

but this doesn't work for me, it runs longTask synchronously and prints "print 1st" last.

1 Answers

I think you can simply use flatMap, which connects the context of the downstream to each inner publisher already. Use then() inside the flatmap function to ignore the result.

Related