Strict mode
Edit pageLast modified: 04 April 2025Starting with version 0.5.0
, the library introduces major changes to the service APIs. The following declarations will be gradually restricted:
StateFlow and SharedFlow
Deprecation level: WARNING
@Rpc
interface Service : RemoteService {
suspend fun old(): StateFlow<Int> // deprecated
suspend fun new(): Flow<Int> // use .stateIn on the client side
}
Fields
Deprecation level: WARNING
@Rpc
interface Service : RemoteService {
val old: Flow<Int> // deprecated
suspend fun new(): Flow<Int> // store flow locally
}
Nested Flows
Deprecation level: WARNING
@Rpc
interface Service : RemoteService {
suspend fun old(): Flow<Flow<Int>> // deprecated
// no particular alternative, depends on the use case
}
Not top-level server flows
Deprecation level: WARNING
data class SpotifyWrapped(val myMusicFlow: Flow<Rap>, val extra: Data)
@Rpc
interface Service : RemoteService {
suspend fun old(): SpotifyWrapped // deprecated
// one should consider message delivery order when calling these
suspend fun new(): Flow<Rap>
suspend fun getData(): Data
}
Non-suspending server flows
Deprecation level: WARNING
data class SpotifyWrapped(val extra: Data)
@Rpc
interface Service : RemoteService {
suspend fun old(): Flow<SpotifyWrapped> // deprecated
fun new(): Flow<SpotifyWrapped>
}
Stream scopes management
Deprecation level: WARNING
The next stream scope management structures are deprecated due to the introduction of non-suspending server flows:
StreamScoped
class and functionstreamScoped
functioninvokeOnStreamScopeCompletion
functionwithStreamScope
function
Stream collection and completion is now bound to the CoroutineScope
in which the flow was collected (server-side flows) or produced (client-side flows).
0.5.x:
@Rpc
interface Service : RemoteService {
suspend fun oldClient(flow: Flow<Int>)
suspend fun oldServer(): Flow<Int>
}
suspend fun consumer(service: Service) {
streamScoped {
service.oldClient(flow { /* ... */ })
service.oldServer().collect {
// ...
}
}
}
0.6.x:
@Rpc
interface Service : RemoteService {
suspend fun newClient(flow: Flow<Int>)
fun newServer(): Flow<Int>
}
fun consumer(service: Service, scope: CoroutineScope) {
val flow = service.new()
scope.launch {
service.newClient(flow { /* ... */ })
flow.collect {
// ...
}
}
}
// or
suspend fun consumer(service: Service) {
service.newClient(flow { /* ... */ })
service.new().collect {
// ...
}
}
Gradle settings
Deprecation levels are controlled by the Gradle rpc
extension:
// build.gradle.kts
plugins {
id("org.jetbrains.kotlinx.rpc.plugin")
}
rpc {
strict {
stateFlow = RpcStrictMode.WARNING
sharedFlow = RpcStrictMode.WARNING
nestedFlow = RpcStrictMode.WARNING
notTopLevelServerFlow = RpcStrictMode.WARNING
fields = RpcStrictMode.WARNING
suspendingServerStreaming = RpcStrictMode.WARNING
streamScopedFunctions = RpcStrictMode.WARNING
}
}
Modes RpcStrictMode.NONE
and RpcStrictMode.ERROR
are available.
warning
Note that setting
RpcStrictMode.NONE
should not be done permanently. All deprecated APIs will become errors in the future without an option to suppress them. Consider your migration path in advance.