Skip to content

Commit 0a2661f

Browse files
committed
Added server APIs (no codegen)
1 parent c9e008c commit 0a2661f

19 files changed

+477
-1
lines changed

grpc/grpc-core/build.gradle.kts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
plugins {
6+
alias(libs.plugins.conventions.kmp)
7+
}
8+
9+
kotlin {
10+
sourceSets {
11+
commonMain {
12+
dependencies {
13+
api(projects.core)
14+
api(libs.coroutines.core)
15+
}
16+
}
17+
18+
jvmMain {
19+
dependencies {
20+
implementation("io.grpc:grpc-util:1.67.1")
21+
implementation("io.grpc:grpc-stub:1.67.1")
22+
implementation("io.grpc:grpc-protobuf:1.67.1")
23+
implementation("io.grpc:grpc-kotlin-stub:1.3.1")
24+
implementation("com.google.protobuf:protobuf-java-util:3.24.1")
25+
implementation("com.google.protobuf:protobuf-kotlin:3.24.1")
26+
}
27+
}
28+
}
29+
}

grpc/grpc-core/gradle.properties

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#
2+
# Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
#
4+
5+
kotlinx.rpc.excludeWasmWasi=true
6+
kotlinx.rpc.excludeWasmJs=true
7+
kotlinx.rpc.excludeJs=true
8+
kotlinx.rpc.excludeNative=true
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package kotlinx.rpc.grpc
6+
7+
import kotlinx.coroutines.CoroutineScope
8+
import kotlinx.coroutines.flow.Flow
9+
import kotlinx.coroutines.flow.SharedFlow
10+
import kotlinx.coroutines.flow.StateFlow
11+
import kotlinx.rpc.RPCCall
12+
import kotlinx.rpc.RPCClient
13+
import kotlinx.rpc.RPCField
14+
import kotlin.coroutines.CoroutineContext
15+
16+
public class GrpcClient : RPCClient {
17+
override val coroutineContext: CoroutineContext
18+
get() = TODO("Not yet implemented")
19+
20+
override suspend fun <T> call(call: RPCCall): T {
21+
TODO("Not yet implemented")
22+
}
23+
24+
override fun <T> registerPlainFlowField(serviceScope: CoroutineScope, field: RPCField): Flow<T> {
25+
error("gRPC client does not support field declarations")
26+
}
27+
28+
override fun <T> registerSharedFlowField(serviceScope: CoroutineScope, field: RPCField): SharedFlow<T> {
29+
error("gRPC client does not support field declarations")
30+
}
31+
32+
override fun <T> registerStateFlowField(serviceScope: CoroutineScope, field: RPCField): StateFlow<T> {
33+
error("gRPC client does not support field declarations")
34+
}
35+
36+
override fun provideStubContext(serviceId: Long): CoroutineContext {
37+
TODO("Not yet implemented")
38+
}
39+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package kotlinx.rpc.grpc
6+
7+
import kotlinx.coroutines.SupervisorJob
8+
import kotlinx.coroutines.job
9+
import kotlinx.rpc.RPC
10+
import kotlinx.rpc.RPCServer
11+
import kotlinx.rpc.grpc.internal.MutableHandlerRegistry
12+
import kotlinx.rpc.grpc.internal.ServerServiceDefinition
13+
import kotlin.coroutines.CoroutineContext
14+
import kotlin.reflect.KClass
15+
import kotlin.time.Duration
16+
17+
public class GrpcServer internal constructor(
18+
override val port: Int = 8080,
19+
builder: ServerBuilder<*>.() -> Unit,
20+
) : RPCServer, Server {
21+
private var isBuilt = false
22+
private lateinit var internalServer: Server
23+
24+
private val serverBuilder: ServerBuilder<*> = ServerBuilder(port).apply(builder)
25+
private val registry: MutableHandlerRegistry by lazy {
26+
MutableHandlerRegistry().apply { serverBuilder.fallbackHandlerRegistry(this) }
27+
}
28+
29+
override val coroutineContext: CoroutineContext
30+
get() = error("coroutineContext is not available for gRPC server builder")
31+
32+
override fun <Service : RPC> registerService(
33+
serviceKClass: KClass<Service>,
34+
serviceFactory: (CoroutineContext) -> Service,
35+
) {
36+
val childJob = SupervisorJob(coroutineContext.job)
37+
val service = serviceFactory(childJob)
38+
39+
val definition: ServerServiceDefinition = getDefinition(service, serviceKClass)
40+
41+
if (isBuilt) {
42+
registry.addService(definition)
43+
} else {
44+
serverBuilder.addService(definition)
45+
}
46+
}
47+
48+
private fun <Service : RPC> getDefinition(
49+
service: Service,
50+
serviceKClass: KClass<Service>,
51+
): ServerServiceDefinition {
52+
// generated locator
53+
TODO("Not yet implemented")
54+
}
55+
56+
internal fun build() {
57+
internalServer = Server(serverBuilder)
58+
isBuilt = true
59+
}
60+
61+
override val isShutdown: Boolean
62+
get() = internalServer.isShutdown
63+
64+
override val isTerminated: Boolean
65+
get() = internalServer.isTerminated
66+
67+
override fun start(): GrpcServer {
68+
internalServer.start()
69+
return this
70+
}
71+
72+
override fun shutdown(): GrpcServer {
73+
internalServer.shutdown()
74+
return this
75+
}
76+
77+
override fun shutdownNow(): GrpcServer {
78+
internalServer.shutdownNow()
79+
return this
80+
}
81+
82+
override suspend fun awaitTermination(duration: Duration): GrpcServer {
83+
internalServer.awaitTermination(duration)
84+
return this
85+
}
86+
}
87+
88+
public fun grpcServer(
89+
port: Int,
90+
configure: ServerBuilder<*>.() -> Unit = {},
91+
builder: RPCServer.() -> Unit = {},
92+
): GrpcServer {
93+
return GrpcServer(port, configure).apply(builder).apply { build() }
94+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package kotlinx.rpc.grpc
6+
7+
import kotlin.time.Duration
8+
9+
public interface Server {
10+
public val port: Int
11+
public val isShutdown: Boolean
12+
public val isTerminated: Boolean
13+
14+
public fun start() : Server
15+
public fun shutdown() : Server
16+
public fun shutdownNow() : Server
17+
public suspend fun awaitTermination(duration: Duration = Duration.INFINITE) : Server
18+
}
19+
20+
internal expect fun Server(builder: ServerBuilder<*>): Server
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
@file:Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
6+
7+
package kotlinx.rpc.grpc
8+
9+
import kotlinx.rpc.grpc.internal.HandlerRegistry
10+
import kotlinx.rpc.grpc.internal.ServerServiceDefinition
11+
12+
public expect abstract class ServerBuilder<T : ServerBuilder<T>> {
13+
public abstract fun addService(service: ServerServiceDefinition): T
14+
15+
public abstract fun fallbackHandlerRegistry(registry: HandlerRegistry?): T
16+
}
17+
18+
internal expect fun ServerBuilder(port: Int): ServerBuilder<*>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
@file:Suppress("MemberVisibilityCanBePrivate")
6+
7+
package kotlinx.rpc.grpc
8+
9+
public interface Status {
10+
public val code: Code
11+
public val description: String?
12+
public val cause: Throwable?
13+
14+
public enum class Code(public val value: Int) {
15+
OK(0),
16+
CANCELLED(1),
17+
UNKNOWN(2),
18+
INVALID_ARGUMENT(3),
19+
DEADLINE_EXCEEDED(4),
20+
NOT_FOUND(5),
21+
ALREADY_EXISTS(6),
22+
PERMISSION_DENIED(7),
23+
RESOURCE_EXHAUSTED(8),
24+
FAILED_PRECONDITION(9),
25+
ABORTED(10),
26+
OUT_OF_RANGE(11),
27+
UNIMPLEMENTED(12),
28+
INTERNAL(13),
29+
UNAVAILABLE(14),
30+
DATA_LOSS(15),
31+
UNAUTHENTICATED(16);
32+
33+
public val valueAscii: ByteArray = value.toString().toByteArray(Charsets.US_ASCII)
34+
}
35+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/*
2+
* Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package kotlinx.rpc.grpc
6+
7+
public interface StatusRuntimeException {
8+
public val status: Status
9+
}
10+
11+
public expect fun StatusRuntimeException(status: Status) : StatusRuntimeException
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
@file:Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
6+
7+
package kotlinx.rpc.grpc.internal
8+
9+
import kotlinx.rpc.internal.utils.InternalRPCApi
10+
11+
@InternalRPCApi
12+
public expect abstract class HandlerRegistry
13+
14+
@InternalRPCApi
15+
public expect class MutableHandlerRegistry constructor() : HandlerRegistry {
16+
internal fun addService(service: ServerServiceDefinition): ServerServiceDefinition?
17+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
* Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
@file:Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
6+
7+
package kotlinx.rpc.grpc.internal
8+
9+
import kotlinx.rpc.internal.utils.InternalRPCApi
10+
11+
@InternalRPCApi
12+
public expect class ServerServiceDefinition

0 commit comments

Comments
 (0)