Правильный способ добавить задержку ответа на запрос в настраиваемый HttpService
Вот моя текущая реализация
HttpService.serve()
@Override
public HttpResponse serve(ServiceRequestContext ctx, HttpRequest req) throws Exception {
return HttpResponse.from(req.aggregate().thenApply(ahr -> {
MyResponse myResponse = Utils.handle(ahr);
HttpResponse httpResponse Utils.toResponse(myResponse);
return httpResponse;
}));
}
У меня есть определяемая пользователем задержка ответа, которая может варьироваться для каждого отдельного запроса-ответа, и это доступно в
myResponse
объект.
Как лучше всего применить эту задержку неблокирующим способом, я вижу некоторые
delay
API, но они защищены внутри
HttpResponse
. Любые дополнительные советы или указатели по дизайну потокового API или декораторам были бы полезны. Я действительно многому научился из кодовой базы Armeria:)
1 ответ
Если вы знаете желаемую задержку еще до использования тела запроса, вы можете просто использовать
HttpResponse.delayed()
:
@Override
public HttpResponse serve(ServiceRequestContext ctx, HttpRequest req) throws Exception {
return HttpResponse.delayed(
HttpResponse.of(200),
Duration.ofSeconds(3),
ctx.eventLoop());
}
Если вам нужно использовать контент или выполнить какую-либо операцию для расчета желаемой задержки, вы можете объединить
HttpResponse.delayed()
с участием
HttpResponse.from()
:
@Override
public HttpResponse serve(ServiceRequestContext ctx, HttpRequest req) throws Exception {
return HttpResponse.from(req.aggregate().thenApply(ahr -> {
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
MyResponse myResponse = Utils.handle(ahr);
HttpResponse httpResponse = Utils.toResponse(myResponse);
Duration myDelay = Utils.delayMillis(...);
return HttpResponse.delayed(httpResponse, myDelay, ctx.eventLoop());
// ^^^^^^^
});
}
Если задержка на самом деле не задержка, а ожидание чего-то, вы можете использовать
CompletableFuture.thenCompose()
который более мощный:
@Override
public HttpResponse serve(ServiceRequestContext ctx, HttpRequest req) throws Exception {
return HttpResponse.from(req.aggregate().thenCompose(ahr -> {
// ^^^^^^^^^^^
My1stResponse my1stRes = Utils.handle(ahr);
// Schedule some asynchronous task that returns another future.
CompletableFuture<My2ndResponse> myFuture = doSomething(my1stRes);
// Map the future into an HttpResponse.
return myFuture.thenApply(my2ndRes -> {
HttpResponse httpRes = Utils.toResponse(my1stRes, my2ndRes);
return httpRes;
});
});
}
Для еще более сложного рабочего процесса я бы рекомендовал вам изучить реализации Reactive Streams, такие как Project Reactor и RxJava, которые предоставляют инструменты, позволяющие избежать ада обратных вызовов.