I have an operation that executes relatively quick, but it is still high in CPU. So I want to delay the response so that there's a minimum of 100ms
I know I can simply do this
@PostMapping(
path = "/Echo/echo",
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public Mono<EchoResponse> echo(@RequestBody EchoRequest request) {
return Mono.just(
EchoResponse.builder().message(request.getMessage()).timestamp(Instant.now()).build())
.delayElement(Duration.ofMillis(100L));
}
But that would always add 100ms
what I'd want is to something like
I am thinking I should be using delayUntil (now that I wrote this)
There is something terrible wrong with your consumer. A fast response should not result in a retry.
I would never built some throttling in a production-application.
delayUntil()
expects a function which doesn't fit well to your use-case.
I see only one way: Measure the timings.
Here is an example.
Caution #1: Written by hand, there are some errors.
Caution #2: Spring-Magic is not part of the method. Serialization and Spring-Filters cannot be measured.
public Mono<EchoResponse> echo(@RequestBody EchoRequest request) {
var startTime = LocalDateTime.now();
var hardWorkedObject = EchoResponse.builder()
.message(request.getMessage())
.timestamp(Instant.now())
.build())
var workedTime = Duration.between(startTime, LocalDateTime.now());
if (workedTime.getMillis() < 100) {
return Observable.timer(100 - workedTime.getMillies())
.take(1)
.map(ignored -> hardWorkedObject)
.toMono();
} else {
return Mono.just(hardWorkedObject);
}
}
First thing is to store the start time. The value would be stored in the context using the following function.
private Context writeStartTimeToContext(Context ctx) {
return ctx.put("startTime", System.currentTimeMillis());
}
Next there needs to be a method that takes in some source data and returns a Mono that is delayed for delayUntil
to use.
/**
* Provide a function to apply a minimum operation time
*
* @param i input type ignored
* @return a mono that is delayed until a target time.
* @param <T> input type that is ignored
*/
private <T> Mono<?> applyMinimumOperationTime(T i) {
return Mono.deferContextual(
ctx ->
Mono.just(
authProperties.getMinimumOperationTimeInMillis()
+ (long) ctx.get("startTime")
- System.currentTimeMillis()))
.filter(delayTime -> delayTime > 0)
.map(Duration::ofMillis)
.flatMap(delayTime -> Mono.just(i).delayElement(delayTime));
}
This can then be applied in the call chain near the end as
someOperationThatCouldBeVeryQuickThatProvidesAMono
...
.delayUntil(this::applyMinimumOperationTime)
.contextWrite(this::writeStartTimeToContext)
...;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.