@@ -2,31 +2,46 @@ package feature
2
2
3
3
import kotlinx.coroutines.CoroutineScope
4
4
import kotlinx.coroutines.Dispatchers
5
- import kotlinx.coroutines.SupervisorJob
6
5
import kotlinx.coroutines.cancel
7
6
import kotlinx.coroutines.channels.Channel
7
+ import kotlinx.coroutines.channels.consumeEach
8
8
import kotlinx.coroutines.flow.MutableStateFlow
9
9
import kotlinx.coroutines.flow.asStateFlow
10
10
import kotlinx.coroutines.flow.receiveAsFlow
11
+ import kotlinx.coroutines.launch
11
12
12
- abstract class Feature <in Command , State , Event >(
13
+ abstract class Feature <Command , State , Event >(
13
14
initialState : State ,
14
15
private val reducer : Reducer <Command , State , Event >,
15
16
) {
16
- val featureScope = CoroutineScope (Dispatchers .Default + SupervisorJob ())
17
+ internal val coroutineScope = CoroutineScope (Dispatchers .Default )
18
+
19
+ private val commands: Channel <Command > = Channel (Channel .UNLIMITED )
17
20
18
21
private val _state = MutableStateFlow (initialState)
22
+
19
23
val state = _state .asStateFlow()
20
24
21
25
private val _events = Channel <Event >(Channel .BUFFERED )
26
+
22
27
val events = _events .receiveAsFlow()
23
28
24
- suspend fun execute (command : Command ) = runCatching {
25
- val (newState, events) = reducer.reduce(_state .value, command)
29
+ init {
30
+ coroutineScope.launch {
31
+ commands.consumeEach { command ->
32
+ val (newState, newEvents) = reducer.reduce(_state .value, command)
33
+
34
+ _state .value = newState
26
35
27
- _state .emit(newState)
36
+ newEvents.forEach { event ->
37
+ _events .send(event)
38
+ }
39
+ }
40
+ }
41
+ }
28
42
29
- events.forEach { event -> _events .send(event) }
43
+ suspend fun execute (command : Command ) = runCatching {
44
+ commands.send(command)
30
45
}.isSuccess
31
46
32
47
open fun <Command , State , Event > Feature <Command , State , Event >.invokeOnClose (block : () -> Unit = {}) {
@@ -37,7 +52,11 @@ abstract class Feature<in Command, State, Event>(
37
52
try {
38
53
invokeOnClose()
39
54
} finally {
40
- featureScope.cancel()
55
+ coroutineScope.cancel()
56
+
57
+ commands.close()
58
+
59
+ _events .close()
41
60
}
42
61
}
43
62
}
0 commit comments