Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions docs/pages/kotlinx-rpc/topics/platforms.topic
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,6 @@
<td><list><li>apple<list><li>ios<list><li>iosArm64</li><li>iosSimulatorArm64</li><li>iosX64</li></list></li><li>macos<list><li>macosArm64</li><li>macosX64</li></list></li><li>watchos<list><li>watchosArm32</li><li>watchosArm64</li><li>watchosDeviceArm64</li><li>watchosSimulatorArm64</li><li>watchosX64</li></list></li><li>tvos<list><li>tvosArm64</li><li>tvosSimulatorArm64</li><li>tvosX64</li></list></li></list></li><li>linux<list><li>linuxArm64</li><li>linuxX64</li></list></li><li>windows<list><li>mingwX64</li></list></li></list></td>
</tr>

<tr>
<td>protobuf-plugin</td>
<td>Jvm Only</td>
<td>-</td>
<td>-</td>
<td>-</td>
</tr>

<tr>
<td>utils</td>
<td>jvm</td>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import util.other.isPublicModule
import util.tasks.ValidatePublishedArtifactsTask

val isGradlePlugin = project.name == "gradle-plugin"
val isProtocGen = project.name == "protoc-gen"
val publishingExtension = project.extensions.findByType<PublishingExtension>()
val globalRootDir: String by extra

Expand Down Expand Up @@ -53,7 +54,7 @@ fun PublishingExtension.configurePublication() {
// mainly for kotlinMultiplatform publication
setPublicArtifactId(project)

if (!isGradlePlugin) {
if (!isGradlePlugin && !isProtocGen) {
fixModuleMetadata(project)
}

Expand Down
13 changes: 10 additions & 3 deletions gradle-conventions/src/main/kotlin/util/publication.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

@file:Suppress("detekt.MaxLineLength")
Expand All @@ -17,16 +17,21 @@ import util.other.getSensitiveProperty
import java.io.File

const val KOTLINX_RPC_PREFIX = "kotlinx-rpc"
const val PROTOC_GEN = "protoc-gen"
const val PROTOC_GEN_KOTLIN_MULTIPLATFORM = "protoc-gen-kotlin-multiplatform"

/**
* Important to configure inside [KotlinTarget.mavenPublication]
* AND in [PublishingExtension.configurePublication] in the conventions-publishing.gradle.kts file.
*/
@Suppress("KDocUnresolvedReference")
@Suppress("KDocUnresolvedReference", "LoggingSimilarMessage")
fun MavenPublication.setPublicArtifactId(project: Project) {
val publication = this

if (!publication.artifactId.startsWith(KOTLINX_RPC_PREFIX)) {
if (publication.artifactId == PROTOC_GEN) {
publication.artifactId = PROTOC_GEN_KOTLIN_MULTIPLATFORM
project.logger.info("Altered artifactId for $name publication: $artifactId")
} else if (!publication.artifactId.startsWith(KOTLINX_RPC_PREFIX)) {
publication.artifactId = "$KOTLINX_RPC_PREFIX-$artifactId"
project.logger.info("Altered artifactId for $name publication: $artifactId")
}
Expand Down Expand Up @@ -101,6 +106,8 @@ private fun String.updateAvailableAtModuleField(projectName: String): String {
// in "available-at" object:
// from: "url": "../../krpc-client-iossimulatorarm64/0.2.0/krpc-client-iossimulatorarm64-0.2.0.module",
// to: "url": "../../kotlinx-rpc-krpc-client-iossimulatorarm64/0.2.0/kotlinx-rpc-krpc-client-iossimulatorarm64-0.2.0.module",
//
// and same idea for protoc-gen
private fun String.updateAvailableAtUrlField(projectName: String, version: String): String {
return replace(
availableAtUrl(projectName, version, "(\\w+)", "(.+)").toRegex(),
Expand Down
1 change: 1 addition & 0 deletions grpc/grpc-core/api/grpc-core.api
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
public final class kotlinx/rpc/grpc/GrpcClient : kotlinx/rpc/RpcClient {
public final fun awaitTermination-VtjQ1oo (JLkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun awaitTermination-VtjQ1oo$default (Lkotlinx/rpc/grpc/GrpcClient;JLkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
public fun call (Lkotlinx/rpc/RpcCall;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun callServerStreaming (Lkotlinx/rpc/RpcCall;)Lkotlinx/coroutines/flow/Flow;
public final fun shutdown ()V
Expand Down
2 changes: 1 addition & 1 deletion grpc/grpc-core/api/grpc-core.klib.api
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ final class kotlinx.rpc.grpc/GrpcClient : kotlinx.rpc/RpcClient { // kotlinx.rpc
final fun shutdown() // kotlinx.rpc.grpc/GrpcClient.shutdown|shutdown(){}[0]
final fun shutdownNow() // kotlinx.rpc.grpc/GrpcClient.shutdownNow|shutdownNow(){}[0]
final suspend fun <#A1: kotlin/Any?> call(kotlinx.rpc/RpcCall): #A1 // kotlinx.rpc.grpc/GrpcClient.call|call(kotlinx.rpc.RpcCall){0§<kotlin.Any?>}[0]
final suspend fun awaitTermination(kotlin.time/Duration) // kotlinx.rpc.grpc/GrpcClient.awaitTermination|awaitTermination(kotlin.time.Duration){}[0]
final suspend fun awaitTermination(kotlin.time/Duration = ...) // kotlinx.rpc.grpc/GrpcClient.awaitTermination|awaitTermination(kotlin.time.Duration){}[0]
}

final class kotlinx.rpc.grpc/GrpcServer : kotlinx.rpc.grpc/Server, kotlinx.rpc/RpcServer { // kotlinx.rpc.grpc/GrpcServer|null[0]
Expand Down
51 changes: 51 additions & 0 deletions grpc/grpc-core/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
/*
* Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

import kotlinx.rpc.buf.tasks.BufGenerateTask
import kotlinx.rpc.proto.kxrpc
import org.gradle.kotlin.dsl.withType

/*
* Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/
Expand Down Expand Up @@ -34,5 +42,48 @@ kotlin {
implementation(libs.protobuf.kotlin)
}
}

jvmTest {
dependencies {
implementation(projects.grpc.grpcCore)
implementation(libs.coroutines.core)
implementation(libs.coroutines.test)
implementation(libs.kotlin.test)

implementation(libs.grpc.stub)
implementation(libs.grpc.netty)
implementation(libs.grpc.protobuf)
implementation(libs.grpc.kotlin.stub)
implementation(libs.protobuf.java.util)
implementation(libs.protobuf.kotlin)
}
}
}
}


protoSourceSets {
jvmTest {
proto {
exclude("exclude/**")
}
}
}

rpc {
grpc {
val globalRootDir: String by extra

protocPlugins.kxrpc {
local {
javaJar("$globalRootDir/protoc-gen/build/libs/protoc-gen-$version-all.jar")
}
}

project.tasks.withType<BufGenerateTask>().configureEach {
if (name.endsWith("Test")) {
dependsOn(gradle.includedBuild("protoc-gen").task(":jar"))
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public class GrpcClient internal constructor(private val channel: ManagedChannel
channel.shutdownNow()
}

public suspend fun awaitTermination(duration: Duration) {
public suspend fun awaitTermination(duration: Duration = Duration.INFINITE) {
channel.awaitTermination(duration)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,16 @@ import kotlin.time.Duration
* providing the ability to host gRPC services.
*
* @property port Specifies the port used by the server to listen for incoming connections.
* @param builder exposes platform-specific Server builder.
* @param configure exposes platform-specific Server builder.
*/
public class GrpcServer internal constructor(
override val port: Int = 8080,
builder: ServerBuilder<*>.() -> Unit,
configure: ServerBuilder<*>.() -> Unit,
) : RpcServer, Server {
private var isBuilt = false
private lateinit var internalServer: Server

private val serverBuilder: ServerBuilder<*> = ServerBuilder(port).apply(builder)
private val serverBuilder: ServerBuilder<*> = ServerBuilder(port).apply(configure)
private val registry: MutableHandlerRegistry by lazy {
MutableHandlerRegistry().apply { serverBuilder.fallbackHandlerRegistry(this) }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package kotlinx.rpc.protobuf.test
package kotlinx.rpc.grpc.core.test

import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
Expand All @@ -22,14 +22,16 @@ abstract class GrpcServerTest {
usePlaintext()
}

val grpcServer = GrpcServer(8080) {
val grpcServer = GrpcServer(8080, builder = {
registerServices()
}
})

grpcServer.start()
test(grpcClient)
grpcServer.shutdown()
grpcServer.awaitTermination()
grpcClient.shutdown()
grpcClient.awaitTermination()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package kotlinx.rpc.protobuf.test
package kotlinx.rpc.grpc.core.test

import StreamingTestService
import kotlinx.coroutines.flow.Flow
Expand All @@ -11,21 +11,22 @@ import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.last
import kotlinx.coroutines.flow.toList
import kotlinx.rpc.RpcServer
import kotlinx.rpc.grpc.test.invoke
import kotlinx.rpc.registerService
import kotlinx.rpc.withService
import kotlin.test.Test
import kotlin.test.assertEquals

class StreamingTestServiceImpl : StreamingTestService {
override fun Server(message: References): Flow<References> {
override fun Server(message: kotlinx.rpc.grpc.test.References): Flow<kotlinx.rpc.grpc.test.References> {
return flow { emit(message); emit(message); emit(message) }
}

override suspend fun Client(message: Flow<References>): References {
override suspend fun Client(message: Flow<kotlinx.rpc.grpc.test.References>): kotlinx.rpc.grpc.test.References {
return message.last()
}

override fun Bidi(message: Flow<References>): Flow<References> {
override fun Bidi(message: Flow<kotlinx.rpc.grpc.test.References>): Flow<kotlinx.rpc.grpc.test.References> {
return message
}
}
Expand All @@ -38,8 +39,8 @@ class StreamingTest : GrpcServerTest() {
@Test
fun testServerStreaming() = runGrpcTest { grpcClient ->
val service = grpcClient.withService<StreamingTestService>()
service.Server(References {
other = Other {
service.Server(kotlinx.rpc.grpc.test.References {
other = kotlinx.rpc.grpc.test.Other {
field= 42
}
}).toList().run {
Expand All @@ -56,8 +57,8 @@ class StreamingTest : GrpcServerTest() {
val service = grpcClient.withService<StreamingTestService>()
val result = service.Client(flow {
repeat(3) {
emit(References {
other = Other {
emit(kotlinx.rpc.grpc.test.References {
other = kotlinx.rpc.grpc.test.Other {
field = 42 + it
}
})
Expand All @@ -72,8 +73,8 @@ class StreamingTest : GrpcServerTest() {
val service = grpcClient.withService<StreamingTestService>()
service.Bidi(flow {
repeat(3) {
emit(References {
other = Other {
emit(kotlinx.rpc.grpc.test.References {
other = kotlinx.rpc.grpc.test.Other {
field = 42 + it
}
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
* Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package kotlinx.rpc.protobuf.test
package kotlinx.rpc.grpc.core.test

import kotlinx.rpc.RpcServer
import kotlinx.rpc.grpc.test.AllPrimitives
import kotlinx.rpc.grpc.test.invoke
import kotlinx.rpc.grpc.test.PrimitiveService
import kotlinx.rpc.registerService
import kotlinx.rpc.withService
import kotlin.test.Test
Expand Down
Loading