|
1 | 1 | <?xml version="1.0" encoding="UTF-8"?> |
2 | 2 | <!-- |
3 | | - - Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. |
| 3 | + - Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. |
4 | 4 | --> |
5 | 5 |
|
6 | 6 | <!DOCTYPE topic |
|
25 | 25 |
|
26 | 26 | @Rpc |
27 | 27 | interface MyService : RemoteService { |
28 | | - suspend fun sendStream(stream: Flow<Int>): Flow<String> |
| 28 | + fun sendStream(stream: Flow<Int>): Flow<String> |
29 | 29 |
|
30 | 30 | suspend fun streamRequest(request: StreamRequest) |
31 | 31 | } |
32 | 32 | </code-block> |
33 | 33 |
|
34 | 34 | <p> |
35 | 35 | Another requirement is that server-side steaming (flows that are returned from a function), |
36 | | - must be the top-level type: |
| 36 | + must be the top-level type and the function must be non-suspending: |
37 | 37 | </p> |
38 | 38 |
|
39 | 39 | <code-block lang="kotlin"> |
|
45 | 45 |
|
46 | 46 | @Rpc |
47 | 47 | interface MyService : RemoteService { |
48 | | - suspend fun serverStream(): Flow<String> // ok |
| 48 | + fun serverStream(): Flow<String> // ok |
| 49 | + suspend fun serverStream(): Flow<String> // not ok |
49 | 50 | suspend fun serverStream(): StreamResult // not ok |
50 | 51 | } |
51 | 52 | </code-block> |
|
55 | 56 | <a href="https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/serializers.md#contextual-serialization">Contextual</a> |
56 | 57 | annotation. |
57 | 58 | </note> |
58 | | - |
59 | | - <p> |
60 | | - To use flows in your code, use the <code>streamScoped</code> function |
61 | | - that will provide your flows with their lifetime: |
62 | | - </p> |
63 | | - |
64 | | - <code-block lang="kotlin"> |
65 | | - @Rpc |
66 | | - interface MyService : RemoteService { |
67 | | - suspend fun sendFlow(flow: Flow<Int>) |
68 | | - } |
69 | | - |
70 | | - val myService = rpcClient.withService<MyService>() |
71 | | - |
72 | | - streamScoped { |
73 | | - val flow = flow { |
74 | | - repeat(10) { i -> |
75 | | - emit(i) |
76 | | - } |
77 | | - } |
78 | | - |
79 | | - myService.sendFlow(flow) |
80 | | - } |
81 | | - </code-block> |
82 | | - <p> |
83 | | - In that case all your flows, including incoming and outgoing, |
84 | | - will work until the <code>streamScoped</code> function completes. |
85 | | - After that, all streams that are still live will be closed. |
86 | | - </p> |
87 | | - <p> |
88 | | - You can have multiple RPC calls and flows inside the <code>streamScoped</code> function, including those from |
89 | | - different services. |
90 | | - </p> |
91 | | - <p> |
92 | | - On the server side, you can use the <code>invokeOnStreamScopeCompletion</code> handler inside your methods |
93 | | - to execute code after <code>streamScoped</code> on the client side has closed. |
94 | | - It might be useful to clean resources, for example. |
95 | | - </p> |
96 | | - <warning> |
97 | | - Note that this API is experimental and may be removed in future releases. |
98 | | - </warning> |
99 | | - <p> |
100 | | - Another way of managing streams is to do it manually. |
101 | | - For this, you can use the <code>StreamScope</code> constructor function together with |
102 | | - <code>withStreamScope</code>: |
103 | | - </p> |
104 | | - <code-block lang="kotlin"> |
105 | | - val streamScope = StreamScope(myJob) |
106 | | - withStreamScope(streamScope) { |
107 | | - // use streams here |
108 | | - } |
109 | | - </code-block> |
110 | 59 | </chapter> |
111 | 60 | </topic> |
0 commit comments