-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Guidance on custom implementations of coroutine dispatchers, and usage of Delay
#3758
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Why do you want to implement your custom I think you raise an interesting point regarding cases when you want to decorate a dispatcher while keeping the |
That would definitely help with the decorator we want to put in our production code. I'd still be keen to have a mechanism to implement my own dispatcher with scheduling support for testing, for the reasons listed above. Albeit not ideal, I'd be fine with using the wrapper if it allowed intercepting scheduling. |
Hi! Any updates on this? I’d really be keen to stop relying on the internal API for the decorator at least. |
Not many updates, unfortunately. Depending on internal API is okay-ish as long as it's done on the application level, not on the library one (e.g. |
Is it ok to wrap abstract class CoroutineDispatcherWrapper(
private val dispatcher: CoroutineDispatcher,
) : CoroutineContext.Element {
override val key: CoroutineContext.Key<*> = dispatcher.key
override fun <R> fold(initial: R, operation: (R, CoroutineContext.Element) -> R): R {
return operation(initial, dispatcher)
}
override fun <E : CoroutineContext.Element> get(key: CoroutineContext.Key<E>): E? {
@Suppress("UNCHECKED_CAST")
return if (this.key == key) dispatcher as E else null
}
override fun minusKey(key: CoroutineContext.Key<*>): CoroutineContext {
return if (this.key == key) EmptyCoroutineContext else dispatcher
}
} looks like in this case wrapper is disappearing when added to class SomeRepository(
private val workerScheduler: WorkerScheduler,
private val timerScheduler: TimerScheduler,
) {
// ...
} where |
FWIW, I think this would be helpful. Our use case is somewhat similar...we want to add Espresso idling resource wrappers for the coroutine dispatchers. |
I've been working on some code that uses a custom implementation of
CoroutineDispatcher
for testing. Our test dispatcher uses fake time, and runseverything on a single thread to ensure that tests are deterministic. It's not
appropriate for end-to-end testing but it works well with a lot of unit tests
(simplicity, speed, determinism). Due to the
inner workings of Kotlin coroutines,
we made our custom dispatcher implement the
Delay
interface to be able tocontrol scheduling, even though
Delay
is marked asan internal API.
Additionally to the test dispatcher, we want to maintain a coroutine dispatcher
decorator that facilitates dispatch/suspension observability. This decorator
would look something like this:
With this decorator, we run into another problem with
Delay
: ifdelegate
actually implements it, we hide it by using the decorator.
Given the above, I wanted to ask some questions:
Are there any plans to make
Delay
public or provide some other public APIin its place? I've seen
one issue from 2020
where it was actually recommended to someone to implement
Delay
, is thisadvice up-to-date? I understand that if we use
Delay
, we run the risk of ourcode getting broken with some future release of Kotlin coroutines.
If not, are custom implementations of dispatchers discouraged? Neither
CoroutineDispatcher
norContinuationInterceptor
are marked as internal so atfirst glance it seems like this is OK but not implementing
Delay
could lead tounexpected behaviour. Is there any guidance on this (I haven't found it in the
documentation but maybe I've missed it)?
The text was updated successfully, but these errors were encountered: