Strict mode
Edit pageLast modified: 25 June 2025Starting with version 0.5.0
, the library introduced major changes to the service APIs. The following declarations are now restricted:
warning
Strict mode is enforced irreversibly since
0.8.0
.
StateFlow and SharedFlow
Deprecation level: ERROR
@Rpc
interface Service {
suspend fun old(): StateFlow<Int> // deprecated
suspend fun new(): Flow<Int> // use .stateIn on the client side
}
Fields
Deprecation level: ERROR
@Rpc
interface Service {
val old: Flow<Int> // deprecated
suspend fun new(): Flow<Int> // store flow locally
}
Nested Flows
Deprecation level: ERROR
@Rpc
interface Service {
suspend fun old(): Flow<Flow<Int>> // deprecated
// no particular alternative, depends on the use case
}
Not top-level server flows
Deprecation level: ERROR
data class SpotifyWrapped(val myMusicFlow: Flow<Rap>, val extra: Data)
@Rpc
interface Service {
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: ERROR
data class SpotifyWrapped(val extra: Data)
@Rpc
interface Service {
suspend fun old(): Flow<SpotifyWrapped> // deprecated
fun new(): Flow<SpotifyWrapped>
}
Stream scopes management
Deprecation level: ERROR
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 {
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 {
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 {
// ...
}
}