@@ -21,8 +21,11 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
21
21
import kotlinx.coroutines.FlowPreview
22
22
import kotlinx.coroutines.channels.Channel.Factory.RENDEZVOUS
23
23
import kotlinx.coroutines.channels.ReceiveChannel
24
+ import kotlinx.coroutines.flow.Flow
24
25
import kotlinx.coroutines.flow.buffer
25
26
import kotlinx.coroutines.flow.catch
27
+ import kotlinx.coroutines.flow.collect
28
+ import kotlinx.coroutines.flow.flow
26
29
import kotlinx.coroutines.flow.produceIn
27
30
28
31
/* *
@@ -31,8 +34,9 @@ import kotlinx.coroutines.flow.produceIn
31
34
* will emit everything from the worker. The channel will be closed when the flow completes.
32
35
*/
33
36
@UseExperimental(FlowPreview ::class , ExperimentalCoroutinesApi ::class )
34
- internal fun <T > CoroutineScope.launchWorker (worker : Worker <T >): ReceiveChannel <T > =
37
+ internal fun <T > CoroutineScope.launchWorker (worker : Worker <T >): ReceiveChannel <ValueOrDone < T > > =
35
38
worker.run ()
39
+ .transformToValueOrDone()
36
40
.catch { e ->
37
41
// Workers that failed (as opposed to just cancelled) should have their failure reason
38
42
// re-thrown from the workflow runtime. If we don't unwrap the cause here, they'll just
@@ -42,3 +46,35 @@ internal fun <T> CoroutineScope.launchWorker(worker: Worker<T>): ReceiveChannel<
42
46
}
43
47
.buffer(RENDEZVOUS )
44
48
.produceIn(this )
49
+
50
+ /* *
51
+ * Pretend we can use ReceiveChannel.onReceiveOrClosed.
52
+ *
53
+ * See https://github.com/Kotlin/kotlinx.coroutines/issues/1584 and
54
+ * https://github.com/square/workflow/issues/626.
55
+ */
56
+ internal class ValueOrDone <out T > private constructor(private val _value : Any? ) {
57
+
58
+ val isDone: Boolean get() = this == = Done
59
+
60
+ @Suppress(" UNCHECKED_CAST" )
61
+ val value: T
62
+ get() {
63
+ check(! isDone)
64
+ return _value as T
65
+ }
66
+
67
+ companion object {
68
+ private val Done = ValueOrDone <Nothing >(null )
69
+
70
+ fun <T > value (value : T ): ValueOrDone <T > = ValueOrDone (value)
71
+ fun done (): ValueOrDone <Nothing > = Done
72
+ }
73
+ }
74
+
75
+ private fun <T > Flow<T>.transformToValueOrDone (): Flow <ValueOrDone <T >> = flow {
76
+ collect {
77
+ emit(ValueOrDone .value(it))
78
+ }
79
+ emit(ValueOrDone .done())
80
+ }
0 commit comments