https://kotlinlang.org logo
#spring
Title
# spring
a

Axel

11/09/2023, 1:21 PM
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

ashmelev

11/09/2023, 3:19 PM
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

Axel

11/09/2023, 3:20 PM
it is ok that i loose data if the app is killed
a

ashmelev

11/09/2023, 3:22 PM
Then your code should be fine
🙌 1
d

Daniel Pitts

11/09/2023, 7:04 PM
Semantic note: 202 Accepted is more appropriate response for that case.
👍 2
a

ashmelev

11/09/2023, 7:06 PM
@Daniel Pitts Good point. My oversight.
d

Daniel Pitts

11/09/2023, 7:10 PM
I would also consider just using a normal
Executor
, rather than
Mono.fromCallable
and
subscribeOn
.
k

kqr

11/09/2023, 8:07 PM
why not async?
d

Daniel Pitts

11/09/2023, 8:08 PM
Executor is more of a fire-and-forget than async, isn't it?
d

Davio

11/09/2023, 8:52 PM
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

Charles Flynn

11/11/2023, 9:29 AM
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

Axel

11/13/2023, 7:48 AM
VT would be very interesting, but I need to wait for all of those dependencies to be stable 🙂
c

corneil

11/21/2023, 10:26 AM
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.
2 Views