Skip to content

Commit

Permalink
Merge pull request #222 from ForteScarlet/v3-dev-reactiveSupport
Browse files Browse the repository at this point in the history
SimpleEventResult的content支持解析并收集reactive等响应式结果
  • Loading branch information
ForteScarlet authored Feb 24, 2022
2 parents bd81633 + bc07df2 commit a4f50fd
Show file tree
Hide file tree
Showing 15 changed files with 356 additions and 88 deletions.
7 changes: 1 addition & 6 deletions apis/simbot-api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,7 @@ tasks.withType<org.jetbrains.dokka.gradle.DokkaTaskPartial>().configureEach {
}
}

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
kotlinOptions {
javaParameters = true
jvmTarget = "1.8"
}
}


kotlin {
// 严格模式
Expand Down
113 changes: 100 additions & 13 deletions apis/simbot-api/src/main/kotlin/love/forte/simbot/event/EventResult.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2021-2022 ForteScarlet <ForteScarlet@163.com>
* Copyright (c) 2021-2022 ForteScarlet <https://github.com/ForteScarlet>
*
* 本文件是 simply-robot (或称 simple-robot 3.x 、simbot 3.x ) 的一部分。
* 本文件是 simply-robot (或称 simple-robot 3.x、simbot 3.x、simbot3) 的一部分。
*
* simply-robot 是自由软件:你可以再分发之和/或依照由自由软件基金会发布的 GNU 通用公共许可证修改之,无论是版本 3 许可证,还是(按你的决定)任何以后版都可以。
*
Expand All @@ -12,13 +12,13 @@
* https://www.gnu.org/licenses/gpl-3.0-standalone.html
* https://www.gnu.org/licenses/lgpl-3.0-standalone.html
*
*
*/

package love.forte.simbot.event

import kotlinx.coroutines.Deferred
import kotlinx.coroutines.future.asCompletableFuture
import love.forte.simbot.Api4J
import love.forte.simbot.event.EventResult.Default.NormalEmpty
import love.forte.simbot.event.EventResult.Default.Truncated
import love.forte.simbot.event.EventResult.Invalid
Expand All @@ -41,7 +41,42 @@ public interface EventResult {

/**
* 此为监听函数所返回的真正内容。
* 对于此内容,
*
* ### Reactive API
*
* 当 [content] 的返回值为 reactive api相关的内容,且当前 [EventResult] 实例为 [SimpleEventResult] 类型的时候,
* 处理器应当对 reactive 的相关api对其进行转化收集。这通常使用在Java使用者或者与其他reactive API配合使用的时候。
*
* 比如当你的函数返回了 [flux](https://projectreactor.io/docs/core/3.4.1/api/reactor/core/publisher/Flux.html),
* 那么它将会被收集为 [List] 后重新作为 [content] 构建为 EventResult.
*
* 同样的,如果你返回的是 [kotlinx.coroutines.flow.Flow], 也会在函数返回后进行收集。
*
* 值得注意的是, 这个行为会在返回值返回后立即执行, 而不是等待所有监听函数执行结束后。
*
* 支持的收集类型有:
* - [kotlinx.coroutines.flow.Flow]
*
* - `org.reactivestreams.Publisher`
* - `reactor.core.publisher.Flux`
* - `reactor.core.publisher.Mono`
*
* - `io.reactivex.CompletableSource`
* - `io.reactivex.SingleSource`
* - `io.reactivex.MaybeSource`
* - `io.reactivex.ObservableSource`
* - `io.reactivex.Flowable`
*
* - `io.reactivex.rxjava3.core.CompletableSource`
* - `io.reactivex.rxjava3.core.SingleSource`
* - `io.reactivex.rxjava3.core.MaybeSource`
* - `io.reactivex.rxjava3.core.ObservableSource`
* - `io.reactivex.rxjava3.core.Flowable`
*
* 但是相对应的,
*
*
* 详情请见 [kotlinx-coroutines-reactive](https://github.com/Kotlin/kotlinx.coroutines/blob/master/reactive/README.md) .
*/
public val content: Any?

Expand Down Expand Up @@ -73,13 +108,11 @@ public interface EventResult {
*/
@JvmOverloads
@JvmStatic
public fun of(content: Any? = null, isTruncated: Boolean = false): EventResult =
if (content == null) {
if (isTruncated) Truncated else NormalEmpty
} else {
EventResultImpl(content, isTruncated)
}

public fun of(content: Any? = null, isTruncated: Boolean = false): EventResult = if (content == null) {
if (isTruncated) Truncated else NormalEmpty
} else {
SimpleEventResult(content, isTruncated)
}


/**
Expand Down Expand Up @@ -119,7 +152,7 @@ public interface EventResult {

/**
* 默认的 [EventResult] 实现,也是部分常见策略下的结果内容。
*
*
* @see Truncated
*/
private sealed class Default : EventResult {
Expand All @@ -140,13 +173,67 @@ public interface EventResult {
/**
* [content] 作为 [Deferred] 的异步函数返回值。
*
* @property content 异步事件的结果内容。
*/
public open class AsyncEventResult(override val content: Deferred<EventResult>) : EventResult {
/**
* 正常情况下,异步任务将不会阻断后续事件的执行。
*/
override val isTruncated: Boolean get() = false

/**
* 将 [content] 转化为 [Future].
*/
@Api4J
public fun contentAsFuture(): Future<EventResult> = content.asCompletableFuture()

/**
* 等待 [content] 的异步任务响应。
*/
@JvmSynthetic
public suspend fun awaitContent(): EventResult = content.await()
}

/**
* [EventResult] 的基础实现类型,是通过 [EventResult.of] 得到的基本结果类型。
*
* [SimpleEventResult.content] 支持收集响应式数据,详情参见 [EventResult.content] 说明。
*
* @see EventResult
* @property content 事件响应内容。支持解析收集响应式数据。
* @property isTruncated 标记是否截断后续事件的执行。
*/
public open class SimpleEventResult
@JvmOverloads constructor(
override val content: Any? = null, override val isTruncated: Boolean = false
) : EventResult {

/**
* 根据当前的 [content] 和 [isTruncated] 拷贝得到一个新的实例,并且允许提供额外的参数覆盖当前内容。
*/
@JvmOverloads
public open fun copy(newContent: Any? = content, newTruncated: Boolean = isTruncated): SimpleEventResult {
return SimpleEventResult(newContent, newTruncated)
}

override fun toString(): String = "SimpleEventResult(content=$content, isTruncated=$isTruncated)"
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is SimpleEventResult) return false

if (content != other.content) return false
if (isTruncated != other.isTruncated) return false

return true
}

override fun hashCode(): Int {
var result = content?.hashCode() ?: 0
result = 31 * result + isTruncated.hashCode()
return result
}

private data class EventResultImpl(override val content: Any?, override val isTruncated: Boolean) : EventResult

}


7 changes: 1 addition & 6 deletions boots/simboot-api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,7 @@ tasks.getByName<Test>("test") {
useJUnit()
}

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
kotlinOptions {
javaParameters = true
jvmTarget = "1.8"
}
}


dependencies {
api(project(":cores:simbot-core"))
Expand Down
7 changes: 1 addition & 6 deletions boots/simboot-core-annotation/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,7 @@ tasks.getByName<Test>("test") {
useJUnit()
}

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
kotlinOptions {
javaParameters = true
jvmTarget = "1.8"
}
}


dependencies {
api(project(":boots:simboot-api"))
Expand Down
22 changes: 15 additions & 7 deletions boots/simboot-core-spring-boot-starter/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,14 @@ tasks.getByName<Test>("test") {
useJUnit()
}

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
kotlinOptions {
javaParameters = true
jvmTarget = "1.8"
repositories {
mavenLocal()
mavenCentral()
maven {
url = uri(Sonatype.`snapshot-oss`.URL)
mavenContent {
snapshotsOnly()
}
}
}

Expand All @@ -52,9 +56,13 @@ dependencies {
testImplementation(V.Kotlinx.Serialization.Properties.notation)
testImplementation(V.Kotlinx.Serialization.Protobuf.notation)

testImplementation(V.Log4j.Api.notation)
testImplementation(V.Log4j.Core.notation)
testImplementation(V.Log4j.Slf4jImpl.notation)
//testImplementation(V.Log4j.Api.notation)
//testImplementation(V.Log4j.Core.notation)
//testImplementation(V.Log4j.Slf4jImpl.notation)

testImplementation("org.springframework.boot:spring-boot-starter-webflux:2.6.3")
testImplementation("love.forte.simbot.component:simbot-component-mirai-boot:3.0.0.preview.3.0-2100.0.1")
// testImplementation(V.Kotlinx.Coroutines.Reactor.notation)
}
repositories {
mavenCentral()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package love.forte.test.webflux

import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.flow
import love.forte.simboot.annotation.Listener
import love.forte.simboot.autoconfigure.EnableSimbot
import love.forte.simbot.PriorityConstant
import love.forte.simbot.event.EventProcessingContext
import love.forte.simbot.event.FriendMessageEvent
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.ResponseBody
import reactor.core.publisher.Mono


/**
*
* @author ForteScarlet
*/
@SpringBootApplication
@EnableSimbot
open class WebfluxApplication

fun main(args: Array<String>) {
runApplication<WebfluxApplication>(*args)
}


@Controller
open class MyController {

@ResponseBody
@GetMapping("/hi")
suspend fun hello(): Map<String, Any> {
delay(100)
return mapOf("name" to "forte", "age" to 10)
}

@Listener
suspend fun FriendMessageEvent.myListen1() = flow {
emit(1)
bot.logger.info("emit: {}", 1)
delay(2000)
emit(2)
bot.logger.info("emit: {}", 2)
}

@Listener
suspend fun FriendMessageEvent.myListen2() = Mono.just(3)

@Listener(priority = PriorityConstant.LAST)
suspend fun FriendMessageEvent.myListen3(context: EventProcessingContext) {
context.results.forEach {
friend().send(it.toString())
}
}

}

This file was deleted.

This file was deleted.

7 changes: 1 addition & 6 deletions boots/simboot-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,7 @@ tasks.getByName<Test>("test") {
useJUnit()
}

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
kotlinOptions {
javaParameters = true
jvmTarget = "1.8"
}
}


repositories {
mavenLocal()
Expand Down
9 changes: 9 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ println("isPublishConfigurable: $isPublishConfigurable")
val secretKeyRingFileKey = "signing.secretKeyRingFile"



subprojects {
println("ROOT SUB: $this")
group = P.Simbot.GROUP
Expand All @@ -65,10 +66,18 @@ subprojects {

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
kotlinOptions {
jvmTarget = "1.8"
javaParameters = true
freeCompilerArgs = freeCompilerArgs + listOf("-Xjvm-default=all")

}
}

tasks.withType<JavaCompile>().configureEach {
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
}

tasks.withType<org.jetbrains.dokka.gradle.DokkaTaskPartial>().configureEach {
dokkaSourceSets {
configureEach {
Expand Down
2 changes: 1 addition & 1 deletion buildSrc/src/main/kotlin/V.kt
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ sealed class V(group: String?, id: String, version: String?) : Dep(group, id, ve
// https://github.com/Kotlin/kotlinx.coroutines
sealed class Coroutines(id: String) : Kotlinx(id = "coroutines-$id", VERSION, true) {
companion object {
const val VERSION = "1.5.2-native-mt"
const val VERSION = "1.6.0-native-mt"
}

object J8 : Coroutines("jdk8")
Expand Down
Loading

0 comments on commit a4f50fd

Please sign in to comment.