From ab0fc990200d01bd901f0cd237829b13ec027fed Mon Sep 17 00:00:00 2001 From: Nikita Katkov Date: Tue, 10 Mar 2026 16:24:46 +0100 Subject: [PATCH] IJPL-238173 [rpc] Mark public and internal API in the fleet.rpc module to expose the necessary components for external plugin developers Absolute minimum of APIs is exposed so far, namely: - RemoteApiDescriptor - RpcException - RPC annotation and their descendants (cherry picked from commit 95b32b92665878ba2a35baad999458a5653eab05) IJ-CR-195627 GitOrigin-RevId: 7e94238626f3ab69743de25653bc64a54857fa85 --- fleet/rpc/api-dump.txt | 60 +++++++++++++++++++ .../srcCommonMain/fleet/rpc/EndpointKind.kt | 3 + fleet/rpc/srcCommonMain/fleet/rpc/FleetApi.kt | 6 +- .../fleet/rpc/client/ClientId.kt | 2 + .../fleet/rpc/client/FleetClient.kt | 5 +- .../fleet/rpc/client/IRpcClient.kt | 7 +++ .../fleet/rpc/client/RpcClient.kt | 2 + .../fleet/rpc/client/RpcInterceptor.kt | 3 + .../fleet/rpc/client/proxy/package-info.java | 5 ++ .../fleet/rpc/core/package-info.java | 5 ++ .../fleet/rpc/core/util/package-info.java | 5 ++ 11 files changed, 100 insertions(+), 3 deletions(-) create mode 100644 fleet/rpc/api-dump.txt create mode 100644 fleet/rpc/srcCommonMain/fleet/rpc/client/proxy/package-info.java create mode 100644 fleet/rpc/srcCommonMain/fleet/rpc/core/package-info.java create mode 100644 fleet/rpc/srcCommonMain/fleet/rpc/core/util/package-info.java diff --git a/fleet/rpc/api-dump.txt b/fleet/rpc/api-dump.txt new file mode 100644 index 000000000000..2373a102ebdc --- /dev/null +++ b/fleet/rpc/api-dump.txt @@ -0,0 +1,60 @@ +fleet.rpc.RemoteApi +fleet.rpc.RemoteApiDescriptor +- a:call(fleet.rpc.RemoteApi,java.lang.String,java.lang.Object[],kotlin.coroutines.Continuation):java.lang.Object +- a:clientStub(kotlin.jvm.functions.Function3):fleet.rpc.RemoteApi +- a:getApiFqn():java.lang.String +- a:getSignature(java.lang.String):fleet.rpc.RpcSignature +@:fleet.rpc.Rpc +- java.lang.annotation.Annotation +f:fleet.rpc.client.DurableKt +- sf:durable(Z,kotlin.jvm.functions.Function2,kotlin.coroutines.Continuation):java.lang.Object +- bs:durable$default(Z,kotlin.jvm.functions.Function2,kotlin.coroutines.Continuation,I,java.lang.Object):java.lang.Object +f:fleet.rpc.client.FleetClientKt +- sf:fleetClient(fleet.rpc.client.ClientId,fleet.rpc.core.TransportFactory,Z,fleet.util.async.DelayStrategy,fleet.rpc.client.RpcInterceptor,java.lang.String):fleet.util.async.Resource +- bs:fleetClient$default(fleet.rpc.client.ClientId,fleet.rpc.core.TransportFactory,Z,fleet.util.async.DelayStrategy,fleet.rpc.client.RpcInterceptor,java.lang.String,I,java.lang.Object):fleet.util.async.Resource +- sf:proxy(fleet.rpc.client.FleetClient,fleet.rpc.RemoteApiDescriptor,fleet.util.UID,fleet.rpc.core.InstanceId):fleet.rpc.RemoteApi +f:fleet.rpc.client.RemoteIsCancelledException +- fleet.rpc.client.RpcClientException +- kotlinx.coroutines.CopyableThrowable +- (java.lang.String,java.lang.Throwable):V +- createCopy():fleet.rpc.client.RemoteIsCancelledException +f:fleet.rpc.client.RouteClosedException +- fleet.rpc.client.RpcClientException +- kotlinx.coroutines.CopyableThrowable +- (fleet.util.UID,java.lang.String,java.lang.Throwable):V +- b:(fleet.util.UID,java.lang.String,java.lang.Throwable,I,kotlin.jvm.internal.DefaultConstructorMarker):V +- createCopy():fleet.rpc.client.RouteClosedException +- f:getRoute():fleet.util.UID +f:fleet.rpc.client.RpcCausalityTimeout +- fleet.rpc.client.RpcClientException +- kotlinx.coroutines.CopyableThrowable +- (java.lang.String,java.lang.Throwable):V +- createCopy():fleet.rpc.client.RpcCausalityTimeout +f:fleet.rpc.client.RpcClientDisconnectedException +- fleet.rpc.client.RpcClientException +- kotlinx.coroutines.CopyableThrowable +- (java.lang.String,java.lang.Throwable):V +- createCopy():fleet.rpc.client.RpcClientDisconnectedException +a:fleet.rpc.client.RpcClientException +- java.lang.RuntimeException +- (java.lang.String,java.lang.Throwable):V +f:fleet.rpc.client.RpcServiceNotReady +- fleet.rpc.client.RpcClientException +- kotlinx.coroutines.CopyableThrowable +- (fleet.rpc.core.RpcMessage$CallRequest,java.lang.Throwable):V +- b:(fleet.rpc.core.RpcMessage$CallRequest,java.lang.Throwable,I,kotlin.jvm.internal.DefaultConstructorMarker):V +- createCopy():fleet.rpc.client.RpcServiceNotReady +f:fleet.rpc.client.RpcTimeoutException +- fleet.rpc.client.RpcClientException +- kotlinx.coroutines.CopyableThrowable +- (java.lang.String,java.lang.Throwable):V +- b:(java.lang.String,java.lang.Throwable,I,kotlin.jvm.internal.DefaultConstructorMarker):V +- createCopy():fleet.rpc.client.RpcTimeoutException +- f:getMsg():java.lang.String +f:fleet.rpc.client.UnresolvedServiceException +- fleet.rpc.client.RpcClientException +- kotlinx.coroutines.CopyableThrowable +- (fleet.rpc.core.InstanceId,java.lang.Throwable):V +- b:(fleet.rpc.core.InstanceId,java.lang.Throwable,I,kotlin.jvm.internal.DefaultConstructorMarker):V +- createCopy():fleet.rpc.client.UnresolvedServiceException +- f:getServiceId():fleet.rpc.core.InstanceId diff --git a/fleet/rpc/srcCommonMain/fleet/rpc/EndpointKind.kt b/fleet/rpc/srcCommonMain/fleet/rpc/EndpointKind.kt index f90a922bf5c7..b25d4fdfdcf7 100644 --- a/fleet/rpc/srcCommonMain/fleet/rpc/EndpointKind.kt +++ b/fleet/rpc/srcCommonMain/fleet/rpc/EndpointKind.kt @@ -1,5 +1,8 @@ package fleet.rpc +import org.jetbrains.annotations.ApiStatus + +@ApiStatus.Internal enum class EndpointKind { Client, Provider diff --git a/fleet/rpc/srcCommonMain/fleet/rpc/FleetApi.kt b/fleet/rpc/srcCommonMain/fleet/rpc/FleetApi.kt index dd4a524bfdab..f8251e43a2b7 100644 --- a/fleet/rpc/srcCommonMain/fleet/rpc/FleetApi.kt +++ b/fleet/rpc/srcCommonMain/fleet/rpc/FleetApi.kt @@ -9,6 +9,7 @@ import fleet.util.cast import fleet.util.letIf import kotlinx.serialization.KSerializer import kotlinx.serialization.builtins.nullable +import org.jetbrains.annotations.ApiStatus /** * Base interface that must be implemented by every Fleet service. @@ -26,6 +27,7 @@ interface RemoteApi @Target(AnnotationTarget.CLASS) annotation class Rpc +@ApiStatus.Internal sealed interface RemoteKind { data class Data(val serializer: KSerializer<*>) : RemoteKind data class Flow(val elementKind: RemoteKind, val nullable: Boolean) : RemoteKind @@ -36,6 +38,7 @@ sealed interface RemoteKind { data class Resource(val descriptor: RemoteApiDescriptor<*>) : RemoteKind } +@ApiStatus.Internal fun RemoteKind.serializer(debugInfo: String): KSerializer { return when (this) { is RemoteKind.Data -> serializer @@ -47,8 +50,9 @@ fun RemoteKind.serializer(debugInfo: String): KSerializer { is RemoteKind.Resource -> error("Resource has no serializer") }.cast() } - +@ApiStatus.Internal data class ParameterDescriptor(val parameterName: String, val parameterKind: RemoteKind) +@ApiStatus.Internal data class RpcSignature(val methodName: String, val parameters: Array, val returnType: RemoteKind) interface RemoteApiDescriptor> { diff --git a/fleet/rpc/srcCommonMain/fleet/rpc/client/ClientId.kt b/fleet/rpc/srcCommonMain/fleet/rpc/client/ClientId.kt index e236dbc4013f..da8ebf1e616b 100644 --- a/fleet/rpc/srcCommonMain/fleet/rpc/client/ClientId.kt +++ b/fleet/rpc/srcCommonMain/fleet/rpc/client/ClientId.kt @@ -4,7 +4,9 @@ package fleet.rpc.client import fleet.util.UID import fleet.util.serialization.DataSerializer import kotlinx.serialization.Serializable +import org.jetbrains.annotations.ApiStatus +@ApiStatus.Internal @Serializable(with = ClientIdSerializer::class) data class ClientId(val uid: UID) diff --git a/fleet/rpc/srcCommonMain/fleet/rpc/client/FleetClient.kt b/fleet/rpc/srcCommonMain/fleet/rpc/client/FleetClient.kt index b75eaae6176a..fa56bd0aa9cf 100644 --- a/fleet/rpc/srcCommonMain/fleet/rpc/client/FleetClient.kt +++ b/fleet/rpc/srcCommonMain/fleet/rpc/client/FleetClient.kt @@ -25,10 +25,11 @@ import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CoroutineName import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow -import org.jetbrains.annotations.ApiStatus.Internal +import org.jetbrains.annotations.ApiStatus import kotlin.concurrent.Volatile import kotlin.coroutines.CoroutineContext +@ApiStatus.Internal class FleetClient internal constructor( val connectionStatus: StateFlow>, val stats: MutableStateFlow, @@ -41,7 +42,7 @@ class FleetClient internal constructor( @Volatile private var poison: CancellationException? = null - @Internal + @ApiStatus.Internal val invocationHandlerFactory: InvocationHandlerFactory = reconnectingRpcClient(connectionStatus) .asHandlerFactory() diff --git a/fleet/rpc/srcCommonMain/fleet/rpc/client/IRpcClient.kt b/fleet/rpc/srcCommonMain/fleet/rpc/client/IRpcClient.kt index 22d795e28399..578240d509e0 100644 --- a/fleet/rpc/srcCommonMain/fleet/rpc/client/IRpcClient.kt +++ b/fleet/rpc/srcCommonMain/fleet/rpc/client/IRpcClient.kt @@ -17,10 +17,12 @@ import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.withContext import kotlinx.coroutines.withTimeoutOrNull +import org.jetbrains.annotations.ApiStatus import kotlin.concurrent.Volatile import kotlin.coroutines.CoroutineContext import kotlin.coroutines.coroutineContext +@ApiStatus.Internal data class Call(val route: UID, val service: InstanceId, val signature: RpcSignature, @@ -35,6 +37,7 @@ internal data class RpcStrategyContextElement(val awaitConnection: Boolean = tru override val key: CoroutineContext.Key<*> get() = RpcStrategyContextElement } +@ApiStatus.Internal suspend fun withoutAwaitingForReconnect(body: suspend CoroutineScope.() -> T): T { val strategy = coroutineContext[RpcStrategyContextElement]?.copy(awaitConnection = false) ?: RpcStrategyContextElement(awaitConnection = false) @@ -43,6 +46,7 @@ suspend fun withoutAwaitingForReconnect(body: suspend CoroutineScope.() -> T } } +@ApiStatus.Internal suspend fun withPrefetchStrategy(prefetchStrategy: PrefetchStrategy, body: suspend CoroutineScope.() -> T): T { val strategy = coroutineContext[RpcStrategyContextElement]?.copy(prefetchStrategy = prefetchStrategy) ?: RpcStrategyContextElement(prefetchStrategy = prefetchStrategy) @@ -51,10 +55,12 @@ suspend fun withPrefetchStrategy(prefetchStrategy: PrefetchStrategy, body: s } } +@ApiStatus.Internal interface IRpcClient { suspend fun call(call: Call, publish: (SuspendInvocationHandler.CallResult) -> Unit) } +@ApiStatus.Internal fun promisingRpcClient(promise: Deferred): IRpcClient { return object : IRpcClient { override suspend fun call(call: Call, publish: (SuspendInvocationHandler.CallResult) -> Unit) { @@ -63,6 +69,7 @@ fun promisingRpcClient(promise: Deferred): IRpcClient { } } +@ApiStatus.Internal fun IRpcClient.asHandlerFactory(): InvocationHandlerFactory = object : InvocationHandlerFactory { override fun handler(arg: ProxyClosure): SuspendInvocationHandler { diff --git a/fleet/rpc/srcCommonMain/fleet/rpc/client/RpcClient.kt b/fleet/rpc/srcCommonMain/fleet/rpc/client/RpcClient.kt index 8af110252829..8a75dbd88f6c 100644 --- a/fleet/rpc/srcCommonMain/fleet/rpc/client/RpcClient.kt +++ b/fleet/rpc/srcCommonMain/fleet/rpc/client/RpcClient.kt @@ -71,6 +71,7 @@ import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.withTimeoutOrNull import kotlinx.serialization.builtins.serializer import kotlinx.serialization.json.Json +import org.jetbrains.annotations.ApiStatus import kotlin.coroutines.Continuation import kotlin.coroutines.coroutineContext import kotlin.coroutines.resumeWithException @@ -90,6 +91,7 @@ private data class OutgoingRequest( private data class OngoingRequest(val request: OutgoingRequest) +@ApiStatus.Internal fun rpcClient( transport: Transport, origin: UID, diff --git a/fleet/rpc/srcCommonMain/fleet/rpc/client/RpcInterceptor.kt b/fleet/rpc/srcCommonMain/fleet/rpc/client/RpcInterceptor.kt index bfbeb19ae0e6..0caaec74e16b 100644 --- a/fleet/rpc/srcCommonMain/fleet/rpc/client/RpcInterceptor.kt +++ b/fleet/rpc/srcCommonMain/fleet/rpc/client/RpcInterceptor.kt @@ -2,7 +2,9 @@ package fleet.rpc.client import fleet.rpc.core.RpcMessage +import org.jetbrains.annotations.ApiStatus +@ApiStatus.Internal interface RpcInterceptor { companion object: RpcInterceptor { override suspend fun interceptCallRequest(request: RpcMessage.CallRequest): RpcMessage.CallRequest { @@ -18,6 +20,7 @@ interface RpcInterceptor { suspend fun interceptCallResult(displayName: String, result: RpcMessage.CallResult) {} } +@ApiStatus.Internal operator fun RpcInterceptor.plus(another: RpcInterceptor): RpcInterceptor { val one = this return object : RpcInterceptor { diff --git a/fleet/rpc/srcCommonMain/fleet/rpc/client/proxy/package-info.java b/fleet/rpc/srcCommonMain/fleet/rpc/client/proxy/package-info.java new file mode 100644 index 000000000000..2595d1cd2ec2 --- /dev/null +++ b/fleet/rpc/srcCommonMain/fleet/rpc/client/proxy/package-info.java @@ -0,0 +1,5 @@ +// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +@Internal +package fleet.rpc.client.proxy; + +import org.jetbrains.annotations.ApiStatus.Internal; diff --git a/fleet/rpc/srcCommonMain/fleet/rpc/core/package-info.java b/fleet/rpc/srcCommonMain/fleet/rpc/core/package-info.java new file mode 100644 index 000000000000..b5e55a510f50 --- /dev/null +++ b/fleet/rpc/srcCommonMain/fleet/rpc/core/package-info.java @@ -0,0 +1,5 @@ +// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +@Internal +package fleet.rpc.core; + +import org.jetbrains.annotations.ApiStatus.Internal; diff --git a/fleet/rpc/srcCommonMain/fleet/rpc/core/util/package-info.java b/fleet/rpc/srcCommonMain/fleet/rpc/core/util/package-info.java new file mode 100644 index 000000000000..6ed3132eeaac --- /dev/null +++ b/fleet/rpc/srcCommonMain/fleet/rpc/core/util/package-info.java @@ -0,0 +1,5 @@ +// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +@Internal +package fleet.rpc.core.util; + +import org.jetbrains.annotations.ApiStatus.Internal;