Last active
March 1, 2021 14:02
-
-
Save erikhuizinga/05a2712bdb0f32c45fa192cd137770e0 to your computer and use it in GitHub Desktop.
UniFlow out of order state publishing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Run with: | |
// kotlinc -script script.main.kts | |
@file:Repository("https://jcenter.bintray.com") | |
@file:DependsOn("io.uniflow:uniflow-core:0.11.6") | |
@file:DependsOn("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.5") | |
import io.uniflow.core.flow.* | |
import io.uniflow.core.flow.data.UIEvent | |
import io.uniflow.core.flow.data.UIState | |
import kotlinx.coroutines.* | |
import java.util.concurrent.Executors | |
import kotlin.reflect.KClass | |
import kotlin.system.exitProcess | |
// Simulate single 'main' thread | |
val coroutineDispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher() | |
val coroutineScope = CoroutineScope(coroutineDispatcher) | |
data class State(val value: Int) : UIState() | |
val defaultValue = 0 | |
val increment = 1 | |
var lastValue = defaultValue | |
// This script cancels itself after a while | |
coroutineScope.launch { | |
delay(100) | |
coroutineScope.cancel() | |
} | |
val uiDataPublisher = object : UIDataPublisher { | |
override suspend fun publishState(state: UIState) = withContext(coroutineDispatcher) { | |
// Publish state on single 'main' thread | |
// Optionally print thread name | |
// println("${Thread.currentThread()} = publishState thread") | |
require(state is State) | |
val value = state.value | |
val lastValueCopy = lastValue | |
val expectedValue = lastValueCopy + increment | |
// Require that values are observed in order | |
// Disable this to see values printed to console, many of which are published out of order! | |
if (value != expectedValue) { | |
System.err.println("value = $value but expected value = $expectedValue after $lastValueCopy") | |
} | |
lastValue = value | |
} | |
override suspend fun publishEvent(event: UIEvent) { | |
TODO("not implemented") | |
} | |
} | |
val uiDataStore = UIDataStore( | |
publisher = uiDataPublisher, | |
defaultState = State(defaultValue), | |
tag = "UIDataStore 1337" | |
) | |
val actionReducer = ActionReducer( | |
uiDataStore = uiDataStore, | |
coroutineScope = coroutineScope, | |
defaultDispatcher = Dispatchers.IO /* This is the default in AndroidDataFlow */, | |
tag = "ActionReducer 1337" | |
) | |
val dataFlow = object : DataFlow { | |
private val actionDispatcher = ActionDispatcher( | |
coroutineScope = coroutineScope, | |
reducer = actionReducer, | |
dataStore = uiDataStore, | |
dataFlow = this, | |
tag = "ActionDispatcher 1337" | |
) | |
override fun action(onAction: suspend ActionFlow.(UIState) -> Unit): ActionFlow = | |
actionDispatcher.action(onAction) | |
override fun action( | |
onAction: suspend ActionFlow.(UIState) -> Unit, | |
onError: suspend ActionFlow.(Exception, UIState) -> Unit | |
): ActionFlow { | |
TODO("not implemented") | |
} | |
override fun <T : UIState> actionOn( | |
stateClass: KClass<T>, | |
onAction: suspend ActionFlow.(T) -> Unit | |
): ActionFlow { | |
TODO("not implemented") | |
} | |
override fun <T : UIState> actionOn( | |
stateClass: KClass<T>, | |
onAction: suspend ActionFlow.(T) -> Unit, | |
onError: suspend ActionFlow.(Exception, UIState) -> Unit | |
): ActionFlow { | |
TODO("not implemented") | |
} | |
override fun getCurrentState(): UIState { | |
TODO("not implemented") | |
} | |
override fun <T : UIState> getCurrentStateOrNull(stateClass: KClass<T>): T? { | |
TODO("not implemented") | |
} | |
} | |
var currentValue = defaultValue | |
// Generate a lot of actions | |
while (coroutineScope.isActive) { | |
currentValue += increment | |
val nextValue = currentValue | |
dataFlow.action { | |
setState { | |
// Optionally print thread name | |
// println("${Thread.currentThread()} = setState thread") | |
// Set the state to the next value | |
State(nextValue) | |
} | |
} | |
} | |
exitProcess(0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment