Skip to content

Commit 7ac04ad

Browse files
committed
Migrated RpcClient and kRPC to new descriptor API
1 parent d089657 commit 7ac04ad

File tree

18 files changed

+242
-209
lines changed

18 files changed

+242
-209
lines changed

core/src/commonMain/kotlin/kotlinx/rpc/RPCCall.kt

Lines changed: 4 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4,47 +4,18 @@
44

55
package kotlinx.rpc
66

7-
import kotlin.reflect.KType
7+
import kotlinx.rpc.descriptor.RpcServiceDescriptor
88

99
/**
1010
* Represents a method or field call of an RPC service.
11-
* Contains all types and values information for the call, so it can be passed to a server.
1211
*
13-
* @property serviceTypeString The service type as a string.
14-
* @property serviceId The id of a service that is unique within [RPCClient] services
1512
* @property callableName The name of the callable. Can be the name of the method or field.
16-
* @property type The type of call;
1713
* @property data The data for the call.
18-
* It may be a generated class with all parameters and their values or empty class for fields.
19-
* @property dataType The [KType] of the [data].
20-
* @property returnType The [KType] of the return type.
14+
* @property descriptor the descriptor of the service, that made the call.
2115
*/
22-
public data class RPCCall(
23-
val serviceTypeString: String,
24-
val serviceId: Long,
16+
public data class RpcCall(
17+
val descriptor: RpcServiceDescriptor<*>,
2518
val callableName: String,
26-
val type: Type,
2719
val data: Any,
28-
val dataType: KType,
29-
val returnType: KType,
30-
) {
31-
public enum class Type {
32-
Method, Field;
33-
}
34-
}
35-
36-
/**
37-
* Represents a field of the RPC service.
38-
* Can be internally converted to a [RPCCall], but it depends on a specific [RPCClient] implementation.
39-
*
40-
* @property serviceTypeString The service type as a string.
41-
* @property serviceId The id of a service that is unique within [RPCClient] services
42-
* @property name The name of the field.
43-
* @property type The [KType] of the field.
44-
*/
45-
public data class RPCField(
46-
val serviceTypeString: String,
4720
val serviceId: Long,
48-
val name: String,
49-
val type: KType
5021
)

core/src/commonMain/kotlin/kotlinx/rpc/RPCClient.kt

Lines changed: 12 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -5,62 +5,35 @@
55
package kotlinx.rpc
66

77
import kotlinx.coroutines.CoroutineScope
8-
import kotlinx.coroutines.flow.Flow
9-
import kotlinx.coroutines.flow.SharedFlow
10-
import kotlinx.coroutines.flow.StateFlow
8+
import kotlinx.coroutines.Deferred
119
import kotlin.coroutines.CoroutineContext
1210

1311
/**
14-
* RPCClient represents an abstraction of a RPC client, that can handle requests from several RPC services,
12+
* [RpcClient] represents an abstraction of an RPC client, that can handle requests from several RPC services,
1513
* transform them, send to the server and handle responses and errors.
1614
* [CoroutineScope] defines the lifetime of the client.
1715
*/
18-
public interface RPCClient : CoroutineScope {
16+
public interface RpcClient : CoroutineScope {
1917
/**
2018
* This method is used by generated clients to perform a call to the server.
2119
*
2220
* @param T type of the result
2321
* @param call an object that contains all required information about the called method,
2422
* that is needed to route it properly to the server.
25-
* @return actual result of the call, e.g. data from the server.
23+
* @return actual result of the call, for example, data from the server.
2624
*/
27-
public suspend fun <T> call(call: RPCCall): T
25+
public suspend fun <T> call(call: RpcCall): T
2826

2927
/**
30-
* Registers Flow<T> field of the interface. Sends initialization request, subscribes to emitted values
31-
* and returns the instance of the flow to be consumed
32-
*
33-
* @param T type parameter for Flow
34-
* @param serviceScope Service's coroutine scope
35-
* @param field object that contains information about the field,
36-
* that is used to be mapped to the corresponding field pn server.
37-
* @return Flow instance to be consumed.
38-
*/
39-
public fun <T> registerPlainFlowField(serviceScope: CoroutineScope, field: RPCField): Flow<T>
40-
41-
/**
42-
* Registers SharedFlow<T> field of the interface. Sends initialization request, subscribes to emitted values
43-
* and returns the instance of the flow to be consumed
44-
*
45-
* @param T type parameter for SharedFlow
46-
* @param serviceScope Service's coroutine scope
47-
* @param field object that contains information about the field,
48-
* that is used to be mapped to the corresponding field pn server.
49-
* @return SharedFlow instance to be consumed.
50-
*/
51-
public fun <T> registerSharedFlowField(serviceScope: CoroutineScope, field: RPCField): SharedFlow<T>
52-
53-
/**
54-
* Registers StateFlow<T> field of the interface. Sends initialization request, subscribes to emitted values
55-
* and returns the instance of the flow to be consumed
28+
* This method is used by generated clients to perform a call to the server.
5629
*
57-
* @param T type parameter for StateFlow
58-
* @param serviceScope Service's coroutine scope
59-
* @param field object that contains information about the field,
60-
* that is used to be mapped to the corresponding field pn server.
61-
* @return StateFlow instance to be consumed.
30+
* @param T type of the result
31+
* @param serviceScope service's coroutine scope
32+
* @param call an object that contains all required information about the called method,
33+
* that is needed to route it properly to the server.
34+
* @return actual result of the call, for example, data from the server
6235
*/
63-
public fun <T> registerStateFlowField(serviceScope: CoroutineScope, field: RPCField): StateFlow<T>
36+
public fun <T> callSync(serviceScope: CoroutineScope, call: RpcCall): Deferred<T>
6437

6538
/**
6639
* Provides child [CoroutineContext] for a new [RemoteService] service stub.

core/src/commonMain/kotlin/kotlinx/rpc/annotations/Rpc.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import kotlinx.rpc.RemoteService
2323
* suspend fun sayHello(firstName: String, lastName: String, age: Int): String
2424
* }
2525
* // client code
26-
* val rpcClient: RPCClient
26+
* val rpcClient: RpcClient
2727
* val myService = rpcClient.withService<MyService>()
2828
* val greetingFromServer = myService.sayHello("Alex", "Smith", 35)
2929
* // server code

core/src/commonMain/kotlin/kotlinx/rpc/awaitFieldInitialization.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
package kotlinx.rpc
66

77
import kotlinx.rpc.descriptor.serviceDescriptorOf
8-
import kotlinx.rpc.internal.RPCDeferredField
8+
import kotlinx.rpc.internal.RpcDeferredField
99
import kotlin.reflect.KClass
1010

1111
/**
@@ -29,9 +29,9 @@ import kotlin.reflect.KClass
2929
public suspend fun <T : RemoteService, R> T.awaitFieldInitialization(getter: T.() -> R): R {
3030
val field = getter()
3131

32-
if (field is RPCDeferredField<*>) {
32+
if (field is RpcDeferredField<*>) {
3333
@Suppress("UNCHECKED_CAST")
34-
return (field as RPCDeferredField<R>).await()
34+
return (field as RpcDeferredField<R>).await()
3535
}
3636

3737
error("Please choose required field for a valid RPC client generated by RPCClient.withService method")

core/src/commonMain/kotlin/kotlinx/rpc/descriptor/RpcServiceDescriptor.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
package kotlinx.rpc.descriptor
66

7-
import kotlinx.rpc.RPCClient
87
import kotlinx.rpc.RemoteService
8+
import kotlinx.rpc.RpcClient
99
import kotlinx.rpc.internal.*
1010
import kotlinx.rpc.internal.utils.ExperimentalRPCApi
1111
import kotlin.reflect.KClass
@@ -42,11 +42,11 @@ public fun <T : RemoteService> serviceDescriptorOf(kClass: KClass<T>): RpcServic
4242
public interface RpcServiceDescriptor<T : RemoteService> {
4343
public val fqName: String
4444

45-
public fun getFields(service: T): List<RPCDeferredField<*>>
45+
public fun getFields(service: T): List<RpcDeferredField<*>>
4646

4747
public fun getCallable(name: String): RpcCallable<T>?
4848

49-
public fun createInstance(serviceId: Long, client: RPCClient): T
49+
public fun createInstance(serviceId: Long, client: RpcClient): T
5050
}
5151

5252
@ExperimentalRPCApi
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
33
*/
44

5-
package kotlinx.rpc.krpc.client.internal
5+
package kotlinx.rpc.internal
66

77
import kotlinx.serialization.Serializable
88

core/src/commonMain/kotlin/kotlinx/rpc/internal/RPCDeferredField.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ package kotlinx.rpc.internal
77
import kotlinx.rpc.internal.utils.InternalRPCApi
88

99
@InternalRPCApi
10-
public interface RPCDeferredField<Self> {
10+
public interface RpcDeferredField<Self> {
1111
public suspend fun await(): Self
1212
}
Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,17 @@
22
* Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
33
*/
44

5-
package kotlinx.rpc.krpc.client.internal
5+
package kotlinx.rpc.internal
66

77
import kotlinx.coroutines.CompletableDeferred
8+
import kotlinx.coroutines.Deferred
89
import kotlinx.coroutines.ExperimentalCoroutinesApi
910
import kotlinx.rpc.UninitializedRPCFieldException
1011
import kotlin.reflect.KProperty
1112

12-
internal class RPCFieldProvider<T, R>(
13+
internal class RpcFieldProvider<T, R>(
1314
private val serviceName: String,
14-
private val deferred: CompletableDeferred<T> = CompletableDeferred(),
15+
private val deferred: Deferred<T> = CompletableDeferred(),
1516
val getter: T.() -> R,
1617
) {
1718
@OptIn(ExperimentalCoroutinesApi::class)
@@ -25,9 +26,9 @@ internal class RPCFieldProvider<T, R>(
2526
}
2627

2728
@Suppress("unused")
28-
internal fun <T> RPCFieldProvider(
29+
internal fun <T> RpcFieldProvider(
2930
serviceName: String,
3031
deferred: CompletableDeferred<T> = CompletableDeferred()
31-
): RPCFieldProvider<T, T> {
32-
return RPCFieldProvider(serviceName, deferred) { this }
32+
): RpcFieldProvider<T, T> {
33+
return RpcFieldProvider(serviceName, deferred) { this }
3334
}
Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,46 @@
22
* Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
33
*/
44

5-
package kotlinx.rpc.krpc.client.internal
5+
package kotlinx.rpc.internal
66

7-
import kotlinx.coroutines.CompletableDeferred
8-
import kotlinx.coroutines.Job
7+
import kotlinx.coroutines.Deferred
98
import kotlinx.coroutines.flow.Flow
109
import kotlinx.coroutines.flow.FlowCollector
1110
import kotlinx.coroutines.flow.SharedFlow
1211
import kotlinx.coroutines.flow.StateFlow
13-
import kotlinx.rpc.internal.RPCDeferredField
14-
import kotlinx.rpc.internal.utils.SupervisedCompletableDeferred
15-
16-
internal sealed class RPCFlow<T, FlowT : Flow<T>>(private val serviceName: String, parent: Job) :
17-
RPCDeferredField<FlowT> {
18-
val deferred: CompletableDeferred<FlowT> = SupervisedCompletableDeferred(parent)
1912

13+
internal sealed class RpcFlow<T, FlowT : Flow<T>>(
14+
private val serviceName: String,
15+
protected val deferred: Deferred<FlowT>,
16+
) : RpcDeferredField<FlowT> {
2017
override suspend fun await(): FlowT {
2118
return deferred.await()
2219
}
2320

24-
internal class Plain<T>(serviceName: String, parent: Job) : RPCFlow<T, Flow<T>>(serviceName, parent),
25-
Flow<T> {
21+
internal class Plain<T>(
22+
serviceName: String,
23+
deferred: Deferred<Flow<T>>,
24+
) : RpcFlow<T, Flow<T>>(serviceName, deferred), Flow<T> {
2625
override suspend fun collect(collector: FlowCollector<T>) {
2726
deferred.await().collect(collector)
2827
}
2928
}
3029

31-
internal class Shared<T>(serviceName: String, parent: Job) : RPCFlow<T, SharedFlow<T>>(serviceName, parent),
32-
SharedFlow<T> {
30+
internal class Shared<T>(
31+
serviceName: String,
32+
deferred: Deferred<SharedFlow<T>>,
33+
) : RpcFlow<T, SharedFlow<T>>(serviceName, deferred), SharedFlow<T> {
3334
override val replayCache: List<T> by rpcProperty { replayCache }
3435

3536
override suspend fun collect(collector: FlowCollector<T>): Nothing {
3637
deferred.await().collect(collector)
3738
}
3839
}
3940

40-
internal class State<T>(serviceName: String, parent: Job) : RPCFlow<T, StateFlow<T>>(serviceName, parent),
41-
StateFlow<T> {
41+
internal class State<T>(
42+
serviceName: String,
43+
deferred: Deferred<StateFlow<T>>,
44+
) : RpcFlow<T, StateFlow<T>>(serviceName, deferred), StateFlow<T> {
4245
override val value: T by rpcProperty { value }
4346

4447
override val replayCache: List<T> by rpcProperty { replayCache }
@@ -48,7 +51,7 @@ internal sealed class RPCFlow<T, FlowT : Flow<T>>(private val serviceName: Strin
4851
}
4952
}
5053

51-
protected fun <R> rpcProperty(getter: FlowT.() -> R): RPCFieldProvider<FlowT, R> {
52-
return RPCFieldProvider(serviceName, deferred, getter)
54+
protected fun <R> rpcProperty(getter: FlowT.() -> R): RpcFieldProvider<FlowT, R> {
55+
return RpcFieldProvider(serviceName, deferred, getter)
5356
}
5457
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
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
6+
7+
import kotlinx.coroutines.CoroutineScope
8+
import kotlinx.coroutines.Deferred
9+
import kotlinx.coroutines.flow.Flow
10+
import kotlinx.coroutines.flow.SharedFlow
11+
import kotlinx.coroutines.flow.StateFlow
12+
import kotlinx.rpc.descriptor.RpcServiceDescriptor
13+
import kotlinx.rpc.internal.FieldDataObject
14+
import kotlinx.rpc.internal.RpcFlow
15+
16+
/**
17+
* Registers Flow<T> field of the interface. Sends initialization request, subscribes to emitted values
18+
* and returns the instance of the flow to be consumed
19+
*
20+
* @param T type parameter for Flow
21+
* @param serviceScope Service's coroutine scope
22+
* @param fieldName the name of the field.
23+
* @param descriptor descriptor of the service, that made the call
24+
* that is used to be mapped to the corresponding field on a server.
25+
* @param serviceId id of the service, that made the call
26+
* @return Flow instance to be consumed.
27+
*/
28+
public fun <T> RpcClient.registerPlainFlowField(
29+
serviceScope: CoroutineScope,
30+
fieldName: String,
31+
descriptor: RpcServiceDescriptor<*>,
32+
serviceId: Long,
33+
): Flow<T> {
34+
return RpcFlow.Plain(descriptor.fqName, initializeFlowField(serviceScope, fieldName, descriptor, serviceId))
35+
}
36+
37+
/**
38+
* Registers SharedFlow<T> field of the interface. Sends initialization request, subscribes to emitted values
39+
* and returns the instance of the flow to be consumed
40+
*
41+
* @param T type parameter for SharedFlow
42+
* @param serviceScope Service's coroutine scope
43+
* @param fieldName the name of the field.
44+
* @param descriptor descriptor of the service, that made the call
45+
* that is used to be mapped to the corresponding field on a server.
46+
* @param serviceId id of the service, that made the call
47+
* @return SharedFlow instance to be consumed.
48+
*/
49+
public fun <T> RpcClient.registerSharedFlowField(
50+
serviceScope: CoroutineScope,
51+
fieldName: String,
52+
descriptor: RpcServiceDescriptor<*>,
53+
serviceId: Long,
54+
): SharedFlow<T> {
55+
return RpcFlow.Shared(descriptor.fqName, initializeFlowField(serviceScope, fieldName, descriptor, serviceId))
56+
}
57+
58+
/**
59+
* Registers StateFlow<T> field of the interface. Sends initialization request, subscribes to emitted values
60+
* and returns the instance of the flow to be consumed
61+
*
62+
* @param T type parameter for StateFlow
63+
* @param serviceScope Service's coroutine scope
64+
* @param fieldName the name of the field.
65+
* @param descriptor descriptor of the service, that made the call
66+
* that is used to be mapped to the corresponding field on a server.
67+
* @param serviceId id of the service, that made the call
68+
* @return StateFlow instance to be consumed.
69+
*/
70+
public fun <T> RpcClient.registerStateFlowField(
71+
serviceScope: CoroutineScope,
72+
fieldName: String,
73+
descriptor: RpcServiceDescriptor<*>,
74+
serviceId: Long,
75+
): StateFlow<T> {
76+
return RpcFlow.State(descriptor.fqName, initializeFlowField(serviceScope, fieldName, descriptor, serviceId))
77+
}
78+
79+
private fun <T, FlowT : Flow<T>> RpcClient.initializeFlowField(
80+
serviceScope: CoroutineScope,
81+
fieldName: String,
82+
descriptor: RpcServiceDescriptor<*>,
83+
serviceId: Long,
84+
): Deferred<FlowT> {
85+
return callSync(serviceScope, RpcCall(descriptor, fieldName, FieldDataObject, serviceId))
86+
}

0 commit comments

Comments
 (0)