Reputation: 14766
I have a Spring Flux application where at some point I need to execute some heavy task on the background, the caller (a HTTP request) does not need to wait until that task completes.
Without reactor, I would just probably use the Async annotation, executing that method on a different thread. With reactor, I am not sure if I should proceed with that approach or if there is already a built-in mechanism that allows me to accomplish this.
For example, given a Controller that accepts a Resource object:
@PostMapping("/create")
public Mono<Resource> create(@Valid @RequestBody Resource r) {
processor.run(r); // the caller should not wait for the resource to be processed
return repository.save(r);
}
And a Processor class:
@Async
void run(Resource r) {
WebClient webClient = WebClient.create("http://localhost:8080");
Mono<String> result = webClient.get()
.retrieve()
.bodyToMono(String.class);
String response = result.block(); //block for now
}
The HTTP caller for /create
should not need to wait until the run
method completes.
Upvotes: 9
Views: 14909
Reputation: 2268
I did some testing, and I think even using subscribe()
as fire and forget will wait for request to complete before returning an answer to the webbrowser or REST-client (at least in my simple tests, it looks like that). So, you have to do the similar of @Async, create another thread:
@PostMapping("/create")
public Mono<Resource> create(@Valid @RequestBody Resource r) {
return processor.run(r)
.subscribeOn(Schedulers.elastic()) // put eveything above this line on another thread
.doOnNext(string -> repository.save(r)); // persist "r", not changing it, though
}
And a Processor class:
Mono<String> run(Resource r) {
WebClient webClient = WebClient.create("http://localhost:8080");
return webClient.get()
.retrieve()
.bodyToMono(String.class);
}
Upvotes: 5
Reputation: 3955
If you are looking for the fire-and-forget pattern implementation, you could just subscribe your publisher
@PostMapping("/create")
public Mono<Resource> create(@Valid @RequestBody Resource r) {
run(r).subscribe();
return repository.save(r);
}
Mono<Void> run(Resource r) {
WebClient webClient = WebClient.create("http://localhost:8080");
return webClient.get()
.retrieve()
.bodyToMono(String.class)
.then();
}
If your publisher executes blocking operations it should be subscribed on other thread with elastic or parallel scheduler.
Upvotes: 8