Hello, I have this endpoint in Spring boot with we...
# spring
a
Hello, I have this endpoint in Spring boot with webflux.
Copy code
@RestController
@RequestMapping("/v1/sensors")
class UpdateSensorEndpoint(
    private val updateSensor: UpdateSensor
) {
    @PutMapping("/{sensorId}")
    internal suspend fun updateSensor(
        @PathVariable("sensorId") sensorId: Long,
        @RequestBody request: SensorUpdateDto
    ): Mono<ResponseEntity<Unit>> {
        Mono.fromCallable { updateSensor.update(sensorId, request) }
            .subscribeOn(Schedulers.boundedElastic())
            .subscribe()

        return Mono.just(ResponseEntity.ok().build())
    }
}
Is this the best way to accept a request, return 200OK immediately and perform processing in the background? I need to achieve a few thousand concurrent requests to this endpoint. The
update()
method could take roughly 500ms-1s to complete
a
You don't say anything about the larger use case, so my comment may not be relevant. But I am concerned about your use of in-memory queuing where you may have 2,000-3,000 "updates" enqueued. Your method will have responded with 200 OK for many requests which, if the server were to fail, would not be processed and simply lost to the ether. If, in your wider use case, these updates are critical, losing thousands of them to an unexpected shutdown would be of greater concern.
a
it is ok that i loose data if the app is killed
a
Then your code should be fine
🙌 1
d
Semantic note: 202 Accepted is more appropriate response for that case.
👍 2
a
@Daniel Pitts Good point. My oversight.
d
I would also consider just using a normal
Executor
, rather than
Mono.fromCallable
and
subscribeOn
.
k
why not async?
d
Executor is more of a fire-and-forget than async, isn't it?
d
You don't need to return a Mono, if you use WebFlux and a suspending function in your controller, it gets translated to a Mono behind the scenes if you use the appropriate dependency. So you could just use regular coroutine logic from that point on, e.g. launch a different coroutine in the global scope
plus1 3
👍 1
c
Ditch WebFlux and wait for Spring Boot 3.2 which I think is any day now and make use of Virtual Threads instead. https://spring.io/blog/2023/09/09/all-together-now-spring-boot-3-2-graalvm-native-images-java-21-and-virtual I'm hoping VTs help to eliminate a lot of usage of WebFlux.
a
VT would be very interesting, but I need to wait for all of those dependencies to be stable 🙂
c
If you are processing a few thousand requests concurrently but they can be async I suggest using a persistent message queue to write the requests and then process them in a listener. You can fine tune the listener processing to match the backing services.