mirror of
https://github.com/mamoe/mirai.git
synced 2025-03-11 21:30:11 +08:00
Fix syncFromEvent
, add Tests
This commit is contained in:
parent
422e8a9b4b
commit
ca216bc492
@ -15,7 +15,6 @@ import kotlinx.coroutines.*
|
||||
import net.mamoe.mirai.utils.SinceMirai
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
import kotlin.jvm.JvmSynthetic
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
@ -37,7 +36,16 @@ suspend inline fun <reified E : Event, R : Any> syncFromEvent(
|
||||
noinline mapper: suspend E.(E) -> R? // 不要 crossinline: crossinline 后 stacktrace 会不正常
|
||||
): R {
|
||||
require(timeoutMillis == -1L || timeoutMillis > 0) { "timeoutMillis must be -1 or > 0" }
|
||||
return syncFromEventOrNull(timeoutMillis, mapper) ?: error("timeout $timeoutMillis ms asyncFromEvent")
|
||||
|
||||
return if (timeoutMillis == -1L) {
|
||||
coroutineScope {
|
||||
syncFromEventImpl<E, R>(E::class, this, mapper)
|
||||
}
|
||||
} else {
|
||||
withTimeout(timeoutMillis) {
|
||||
syncFromEventImpl<E, R>(E::class, this, mapper)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -54,19 +62,13 @@ suspend inline fun <reified E : Event, R : Any> syncFromEvent(
|
||||
@JvmSynthetic
|
||||
@SinceMirai("0.38.0")
|
||||
suspend inline fun <reified E : Event, R : Any> syncFromEventOrNull(
|
||||
timeoutMillis: Long = -1,
|
||||
timeoutMillis: Long,
|
||||
noinline mapper: suspend E.(E) -> R? // 不要 crossinline: crossinline 后 stacktrace 会不正常
|
||||
): R? {
|
||||
require(timeoutMillis == -1L || timeoutMillis > 0) { "timeoutMillis must be -1 or > 0" }
|
||||
require(timeoutMillis > 0) { "timeoutMillis must be > 0" }
|
||||
|
||||
return if (timeoutMillis == -1L) {
|
||||
coroutineScope {
|
||||
syncFromEventOrNullImpl<E, R>(E::class, this, mapper)
|
||||
}
|
||||
} else {
|
||||
withTimeoutOrNull(timeoutMillis) {
|
||||
syncFromEventOrNullImpl<E, R>(E::class, this, mapper)
|
||||
}
|
||||
return withTimeoutOrNull(timeoutMillis) {
|
||||
syncFromEventImpl<E, R>(E::class, this, mapper)
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,7 +85,7 @@ suspend inline fun <reified E : Event, R : Any> syncFromEventOrNull(
|
||||
@Suppress("DeferredIsResult")
|
||||
@SinceMirai("0.38.0")
|
||||
inline fun <reified E : Event, R : Any> CoroutineScope.asyncFromEventOrNull(
|
||||
timeoutMillis: Long = -1,
|
||||
timeoutMillis: Long,
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
noinline mapper: suspend E.(E) -> R? // 不要 crossinline: crossinline 后 stacktrace 会不正常
|
||||
): Deferred<R?> {
|
||||
@ -123,11 +125,11 @@ inline fun <reified E : Event, R : Any> CoroutineScope.asyncFromEvent(
|
||||
//////////////
|
||||
|
||||
@PublishedApi
|
||||
internal suspend fun <E : Event, R> syncFromEventOrNullImpl(
|
||||
internal suspend fun <E : Event, R> syncFromEventImpl(
|
||||
eventClass: KClass<E>,
|
||||
coroutineScope: CoroutineScope,
|
||||
mapper: suspend E.(E) -> R?
|
||||
): R? = suspendCoroutine { cont ->
|
||||
): R = suspendCancellableCoroutine { cont ->
|
||||
coroutineScope.subscribe(eventClass) {
|
||||
cont.resumeWith(kotlin.runCatching {
|
||||
mapper.invoke(this, it) ?: return@subscribe ListeningStatus.LISTENING
|
||||
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.message
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.TimeoutCancellationException
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withTimeout
|
||||
import net.mamoe.mirai.event.TestEvent
|
||||
import net.mamoe.mirai.event.broadcast
|
||||
import net.mamoe.mirai.event.syncFromEvent
|
||||
import net.mamoe.mirai.test.runBlocking
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertFailsWith
|
||||
|
||||
internal class SubscribingGetTest {
|
||||
|
||||
@Test
|
||||
fun testSyncFromEvent(): Unit = runBlocking {
|
||||
withTimeout(500) {
|
||||
suspendCoroutine<Unit> { cont ->
|
||||
launch {
|
||||
syncFromEvent(5000) { _: TestEvent ->
|
||||
cont.resume(Unit)
|
||||
}
|
||||
}
|
||||
launch {
|
||||
TestEvent().broadcast()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSyncFromEventTimeout() {
|
||||
runBlockingWithTimeout(500) {
|
||||
assertFailsWith<TimeoutCancellationException> {
|
||||
syncFromEvent(100) { _: TestEvent -> }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun <R> runBlockingWithTimeout(
|
||||
millis: Long,
|
||||
context: CoroutineContext = EmptyCoroutineContext,
|
||||
block: suspend CoroutineScope.() -> R
|
||||
): R = runBlocking(context) {
|
||||
withTimeout(millis, block)
|
||||
}
|
Loading…
Reference in New Issue
Block a user