armeria
armeria copied to clipboard
Support coroutines in `HttpService`.
Similar to
- #4669
- #4725
We should have HttpService based on coroutines. Currently, only way to implement a suspend http service is using AnnotatedService. In some scenarios, users might want to use the HttpService or AbstractHttpService, which in my opinion has more granularly defined signatures which seem less like magic.
Sample proposed implementation 1 (inheritance)
abstract class CoroutineHttpService : HttpService {
final override fun serve(ctx: ServiceRequestContext, req: HttpRequest): HttpResponse {
val future = CoroutineScope(ctx.asCoroutineContext()).future {
serveAsync(ctx, req)
}
return HttpResponse.of(future)
}
abstract suspend fun serveAsync(ctx: ServiceRequestContext, req: HttpRequest): HttpResponse
}
Sample proposed implementation 2 (composition)
interface CoroutineHttpService {
fun serve(ctx: ServiceRequestContext, req: HttpRequest): HttpResponse
}
fun CoroutineHttpService.asHttpService(): HttpService {
return HttpService { ctx, req ->
HttpResponse.of(CoroutineScope(ctx.asCoroutineContext()).future {
serve(ctx, req)
})
}
}
Ditto for AbstractHttpService.
Inheritance
Pros:
- Drop-in replacement to
HttpServicebecause it inherits.
Cons:
- Function name needs to be different such as
serveAsyncorcoServe. - Needs to be an abstract class to prevent overriding
serve.
Composition
Pros:
- Method signatures are the same
- Interface, similar to
HttpService.
Cons:
- Need to use
.asHttpService()method to convert to anHttpService
Also need to check if we lose any valuable method if we don't inherit HttpService.