Skip to content

Commit

Permalink
Merge pull request #792 from simple-robot/blocking-runner
Browse files Browse the repository at this point in the history
将 suspend-transformer 模块的异步相关API和 `Collectable` 的异步相关API内所有的 `CoroutineScope` 参数默认值调整为 `GlobalScope` 并增加与之相关的部分警告或说明
  • Loading branch information
ForteScarlet authored Feb 15, 2024
2 parents d645c0e + 0dcbd70 commit 7b7bef1
Show file tree
Hide file tree
Showing 14 changed files with 362 additions and 146 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test-v4-branch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ jobs:
uses: actions/upload-artifact@v4
if: ${{ always() }}
with:
name: TestReports
name: test-reports-${{ matrix.os }}
path: build/test-reports
retention-days: 7
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Project https://github.com/simple-robot/simpler-robot
* Email [email protected]
*
* This file is part of the Simple Robot Library.
* This file is part of the Simple Robot Library (Alias: simple-robot, simbot, etc.).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
Expand All @@ -24,12 +24,17 @@
package love.forte.simbot.common.collectable

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.asFlow
import love.forte.simbot.common.async.Async
import love.forte.simbot.common.async.asAsync
import love.forte.simbot.common.function.Action
import love.forte.simbot.suspendrunner.reserve.SuspendReserve
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.jvm.JvmSynthetic

/**
Expand Down Expand Up @@ -77,6 +82,42 @@ public interface Collectable<out T> {
*/
public fun asFlow(): Flow<T>

/**
* 使用 [SuspendReserve.Transformer] 对 [flow][asFlow] 的值进行转化处理。
* 例如在 JVM 中,可以使用 `SuspendReserves.flux()` 转化为 `reactor.core.publisher.Flux`
* 或使用 `SuspendReserves.list()` 转化为 [List]。
*
* ```Kotlin
* val flux: Flow<Int> = ...
* val list = flux.transform(transformer = flux())
* ```
*
* **注意:部分转化器可能会要求运行时存在一些依赖,请注意参考它们的注释与说明。**
*
* 建议主要使用 [transform] 转化为其他响应式类型,例如 `reactor.core.publisher.Flux`。
* 对列表等普通的集合类型可以选择其他可能有更多判断与优化的API,
* 例如 Java 使用者可选择 `Collectables.toList`。
*
* @param scope 提供给 [SuspendReserve.Transformer] 的作用域。默认会使用 [GlobalScope]。
* @param context 提供给 [SuspendReserve.Transformer] 的作用域。默认会使用 [EmptyCoroutineContext]。
* @param transformer 转化器实现。
*/
public fun <R> transform(scope: CoroutineScope, context: CoroutineContext, transformer: SuspendReserve.Transformer<Flow<T>, R>): R =
transformer.invoke(scope, context) { asFlow() }

/**
* 使用 [SuspendReserve.Transformer] 对 [flow][asFlow] 的值进行转化处理。
* 更多说明参考全量参数的重载函数。
*
* 默认使用 [GlobalScope] 作为协程作用域、使用 [EmptyCoroutineContext] 作为协程上下文。
*
* _Java 友好的接口重载函数_
*
* @see transformer
*/
@OptIn(DelicateCoroutinesApi::class)
public fun <R> transform(transformer: SuspendReserve.Transformer<Flow<T>, R>): R =
transform(scope = GlobalScope, context = EmptyCoroutineContext, transformer = transformer)
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2024. ForteScarlet.
*
* Project https://github.com/simple-robot/simpler-robot
* Email [email protected]
*
* This file is part of the Simple Robot Library (Alias: simple-robot, simbot, etc.).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Lesser GNU General Public License for more details.
*
* You should have received a copy of the Lesser GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/

package love.forte.simbot.common.coroutines

import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers

/**
* 在 JVM 和 native 平台下,得到 `Dispatchers.IO`;
* 在其他没有 `IO` 调度器的平台下得到 [Dispatchers.Default]。
*
*/
public expect val Dispatchers.IOOrDefault: CoroutineDispatcher
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2024. ForteScarlet.
*
* Project https://github.com/simple-robot/simpler-robot
* Email [email protected]
*
* This file is part of the Simple Robot Library (Alias: simple-robot, simbot, etc.).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Lesser GNU General Public License for more details.
*
* You should have received a copy of the Lesser GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/

package love.forte.simbot.common.coroutines

import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers

/**
* 得到 [Dispatchers.Default]。
*
* @see Dispatchers.Default
*/
public actual inline val Dispatchers.IOOrDefault: CoroutineDispatcher
get() = Default
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Project https://github.com/simple-robot/simpler-robot
* Email [email protected]
*
* This file is part of the Simple Robot Library.
* This file is part of the Simple Robot Library (Alias: simple-robot, simbot, etc.).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
Expand Down Expand Up @@ -33,13 +33,11 @@ import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.flow.transform
import kotlinx.coroutines.future.future
import kotlinx.coroutines.reactor.asFlux
import love.forte.simbot.annotations.InternalSimbotAPI
import love.forte.simbot.common.async.Async
import love.forte.simbot.common.async.asAsync
import love.forte.simbot.common.collection.asIterator
import love.forte.simbot.common.function.Action
import love.forte.simbot.suspendrunner.reserve.SuspendReserve
import love.forte.simbot.suspendrunner.runInAsync
import love.forte.simbot.suspendrunner.runInNoScopeBlocking
import reactor.core.publisher.Flux
import java.util.*
Expand Down Expand Up @@ -282,21 +280,22 @@ public fun <T> Collectable<T>.toList(): List<T> = when (this) {

/**
* 将 [Collectable] 异步地收集为 [List]。
* 如果 [scope] 为 `null`,则会视情况选择使用一个内部的 CoroutineScope 异步调度器
* (see [runInAsync])
* 如果 [scope] 为 `null`,则会视情况使用 [GlobalScope]
* 或使用 [CompletableFuture.supplyAsync]。
*
* @see runInAsync
* **注意:如果没有指定 [scope] 且在可能会使用 [GlobalScope] 的情况下,**
* **你应当了解 [GlobalScope] 的特性与注意事项。**
*
* @see GlobalScope
* @see CompletableFuture.supplyAsync
*/
@OptIn(InternalSimbotAPI::class)
@OptIn(DelicateCoroutinesApi::class)
@JvmOverloads
public fun <T> Collectable<T>.toListAsync(scope: CoroutineScope? = null): CompletableFuture<List<T>> = when (this) {
is SynchronouslyIterateCollectable -> scope?.future { toList() }
?: CompletableFuture.supplyAsync { toList() }

else -> scope?.future { asFlow().toList() }
?: runInAsync { asFlow().toList() }
else -> (scope ?: GlobalScope).future { asFlow().toList() }
}

/// collector
Expand All @@ -319,14 +318,16 @@ public fun <T, R> Collectable<T>.collect(collector: Collector<T, *, R>): R {

/**
* 使用 [Collector] **异步地**收集 [Collectable] 中的元素。
* 如果 [scope] 为 `null`,则会视情况选择使用一个内部的 CoroutineScope 异步调度器
* (see [runInAsync])
* 如果 [scope] 为 `null`,则会视情况使用 [GlobalScope]
* 或使用 [CompletableFuture.supplyAsync]。
*
* @see runInAsync
* **注意:如果没有指定 [scope] 且在可能会使用 [GlobalScope] 的情况下,**
* **你应当了解 [GlobalScope] 的特性与注意事项。**
*
* @see GlobalScope
* @see CompletableFuture.supplyAsync
*/
@OptIn(InternalSimbotAPI::class)
@OptIn(DelicateCoroutinesApi::class)
@JvmOverloads
public fun <T, R> Collectable<T>.collectAsync(
scope: CoroutineScope? = null,
Expand All @@ -341,9 +342,8 @@ public fun <T, R> Collectable<T>.collectAsync(
?: CompletableFuture.supplyAsync { asSequence().asStream().collect(collector) }
}

else -> {
scope?.future { asFlow().collectBy(scope = scope, collector = collector) }
runInAsync { asFlow().collectBy(scope = this, collector = collector) }
else -> (scope ?: GlobalScope).let { s ->
s.future { asFlow().collectBy(scope = s, collector = collector) }
}
}
}
Expand All @@ -360,14 +360,20 @@ public fun <T, R> Collectable<T>.collectAsync(
* 对列表等普通的集合类型可以选择其他可能有更多判断与优化的API,
* 例如 [Collectable.toList]。
*
* @see Collectable.transform
*/
@OptIn(DelicateCoroutinesApi::class)
@JvmOverloads
@Deprecated(
"Just use Collectable.transform", ReplaceWith(
"transform(scope, EmptyCoroutineContext, transformer)",
"kotlin.coroutines.EmptyCoroutineContext"
), level = DeprecationLevel.ERROR
)
public fun <T, R> Collectable<T>.transform(
scope: CoroutineScope = GlobalScope,
transformer: SuspendReserve.Transformer<Flow<T>, R>
): R =
transformer(scope, EmptyCoroutineContext) { asFlow() }
): R = transform(scope, EmptyCoroutineContext, transformer)

/// reactor

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2024. ForteScarlet.
*
* Project https://github.com/simple-robot/simpler-robot
* Email [email protected]
*
* This file is part of the Simple Robot Library (Alias: simple-robot, simbot, etc.).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Lesser GNU General Public License for more details.
*
* You should have received a copy of the Lesser GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/

package love.forte.simbot.common.coroutines

import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers

/**
* 得到 [Dispatchers.IO]。
*
* @see Dispatchers.IO
*/
public actual inline val Dispatchers.IOOrDefault: CoroutineDispatcher
get() = IO
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2024. ForteScarlet.
*
* Project https://github.com/simple-robot/simpler-robot
* Email [email protected]
*
* This file is part of the Simple Robot Library (Alias: simple-robot, simbot, etc.).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Lesser GNU General Public License for more details.
*
* You should have received a copy of the Lesser GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/

package love.forte.simbot.common.coroutines

import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO

/**
* 得到 [Dispatchers.IO]。
*
* @see Dispatchers.IO
*/
public actual inline val Dispatchers.IOOrDefault: CoroutineDispatcher
get() = IO
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2024. ForteScarlet.
*
* Project https://github.com/simple-robot/simpler-robot
* Email [email protected]
*
* This file is part of the Simple Robot Library (Alias: simple-robot, simbot, etc.).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Lesser GNU General Public License for more details.
*
* You should have received a copy of the Lesser GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/

package love.forte.simbot.common.coroutines

import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers

/**
* 得到 [Dispatchers.Default]。
*
* @see Dispatchers.Default
*/
public actual inline val Dispatchers.IOOrDefault: CoroutineDispatcher
get() = Default
Loading

0 comments on commit 7b7bef1

Please sign in to comment.