More proper overloads with suspend handlers#413
Conversation
| * When a protocol call is occurred it starts a new coroutine on [scope] passing [coroutineContext] and [coroutineStart] to it. | ||
| * [cancellationScheduler] and [handlerScheduler] are passed to [IRdEndpoint.set] | ||
| */ | ||
| fun <TReq, TRes> IRdEndpoint<TReq, TRes>.setSuspend( |
There was a problem hiding this comment.
To be honest, I find this method a little strange
-
CoroutineContext often encompasses a dispatcher. passing coroutineContext + handlerScheduler looks contradictory.
-
I don't see any reason to pass outer scope here. This rd-call handler has his own scope/lifetime, which is cancelled when the counterpart scope/lifetime is cancelled, having two sopes looks also looks contradictory to me.
-
In your implementation we lose coroutine cancellation, because you don't use a lifetime received with the request to create the coroutine.
-
In this method we first go to the handlerScheduler (the protocol scheduler in most cases) and only after that we go to coroutineContext, in some cases this can be a problem if for example the main thread is stuck, but we don't really need the main thread at all, this can cause performance problems.
So I believe that we don't need that kind of API in the platform, because that API has a lot of non-obvious and contradictory moments, but at the same time it's easy to write that kind of code in your specific case.
I would prefer that kind of API:
fun <TReq, TRes> IRdEndpoint<TReq, TRes>.setSuspend(coroutineContext: CoroutineContext, handler: suspend CoroutineScope.(Lifetime, TReq) -> TRes) {
val dispatcher = coroutineContext[ContinuationInterceptor] as? CoroutineDispatcher
requireNotNull(dispatcher) { "coroutineContext: $coroutineContext doesn't have a CoroutineDispatcher" }
val scheduler = dispatcher.asRdScheduler
set(cancellationScheduler = SynchronousScheduler, scheduler) { lt, req ->
lt.startAsync(coroutineContext, CoroutineStart.UNDISPATCHED) { handler(lt, req) }.toRdTask()
}
}
Or we can use protocol dispatcher in case if coroutine context doesn't have corotineDispatcher
| import kotlin.coroutines.CoroutineContext | ||
| import kotlin.coroutines.EmptyCoroutineContext | ||
|
|
||
| @Deprecated("Use the overload with CoroutineScope and CoroutineContext and pass all required context elements") |
There was a problem hiding this comment.
I don't see any reason do deprecate this method, and more over force people to pass CoroutineScope here
No description provided.