From 0b5b4481d2e45b39c7eef02f992afa00e1e12523 Mon Sep 17 00:00:00 2001 From: Yigit Ozgumus Date: Mon, 29 Jul 2024 13:38:41 +0300 Subject: [PATCH 1/3] Remove signal and effect handler --- .../transformer/handler/EffectHandler.kt | 25 ------------------- .../transformer/handler/SignalHandler.kt | 21 ---------------- 2 files changed, 46 deletions(-) delete mode 100644 transmission/src/main/java/com/trendyol/transmission/transformer/handler/EffectHandler.kt delete mode 100644 transmission/src/main/java/com/trendyol/transmission/transformer/handler/SignalHandler.kt diff --git a/transmission/src/main/java/com/trendyol/transmission/transformer/handler/EffectHandler.kt b/transmission/src/main/java/com/trendyol/transmission/transformer/handler/EffectHandler.kt deleted file mode 100644 index 80bc133..0000000 --- a/transmission/src/main/java/com/trendyol/transmission/transformer/handler/EffectHandler.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.trendyol.transmission.transformer.handler - -import com.trendyol.transmission.Transmission - -fun interface EffectHandler { - suspend fun CommunicationScope.onEffect(effect: Transmission.Effect) -} - -fun buildGenericEffectHandler( - onEffect: suspend CommunicationScope.(effect: Transmission.Effect) -> Unit -): EffectHandler { - return EffectHandler { effect -> - onEffect(effect) - } -} - -inline fun buildTypedEffectHandler( - crossinline onEffect: suspend CommunicationScope.(effect: E) -> Unit -): EffectHandler { - return EffectHandler { incomingEffect -> - incomingEffect.takeIf { it is E }?.let { effect -> - onEffect(effect as E) - } - } -} diff --git a/transmission/src/main/java/com/trendyol/transmission/transformer/handler/SignalHandler.kt b/transmission/src/main/java/com/trendyol/transmission/transformer/handler/SignalHandler.kt deleted file mode 100644 index 93d957b..0000000 --- a/transmission/src/main/java/com/trendyol/transmission/transformer/handler/SignalHandler.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.trendyol.transmission.transformer.handler - -import com.trendyol.transmission.Transmission - -fun interface SignalHandler { - suspend fun CommunicationScope.onSignal(signal: Transmission.Signal) -} - -fun buildGenericSignalHandler( - onSignal: suspend CommunicationScope.(signal: Transmission.Signal) -> Unit -): SignalHandler { - return SignalHandler { signal -> onSignal(signal) } -} - -inline fun buildTypedSignalHandler( - crossinline onSignal: suspend CommunicationScope.(signal: S) -> Unit -): SignalHandler { - return SignalHandler { incomingSignal -> - incomingSignal.takeIf { it is S }?.let { signal -> onSignal(signal as S) } - } -} From 4094bbd7e287621cbfc65d8c7c4aa47284641cd6 Mon Sep 17 00:00:00 2001 From: Yigit Ozgumus Date: Mon, 29 Jul 2024 13:38:43 +0300 Subject: [PATCH 2/3] Introduce Handler Registry --- .../transformer/handler/HandlerRegistry.kt | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 transmission/src/main/java/com/trendyol/transmission/transformer/handler/HandlerRegistry.kt diff --git a/transmission/src/main/java/com/trendyol/transmission/transformer/handler/HandlerRegistry.kt b/transmission/src/main/java/com/trendyol/transmission/transformer/handler/HandlerRegistry.kt new file mode 100644 index 0000000..fed2ee9 --- /dev/null +++ b/transmission/src/main/java/com/trendyol/transmission/transformer/handler/HandlerRegistry.kt @@ -0,0 +1,47 @@ +@file:Suppress("UNCHECKED_CAST") + +package com.trendyol.transmission.transformer.handler + +import com.trendyol.transmission.Transmission +import com.trendyol.transmission.transformer.Transformer +import kotlin.reflect.KClass + +class HandlerScope(val handlerRegistry: HandlerRegistry) + +fun Transformer.handlerRegistry(scope: HandlerScope.() -> Unit): HandlerRegistry { + val handlerRegistry = HandlerRegistry() + HandlerScope(handlerRegistry).apply(scope) + return handlerRegistry +} + +inline fun HandlerScope.registerEffect(noinline lambda: suspend CommunicationScope.(effect: T) -> Unit) { + handlerRegistry.registerEffect(lambda) +} + +inline fun HandlerScope.registerSignal(noinline lambda: suspend CommunicationScope.(signal: T) -> Unit) { + handlerRegistry.registerSignal(lambda) +} + +class HandlerRegistry internal constructor() { + + @PublishedApi + internal val signalHandlerRegistry = + mutableMapOf, suspend CommunicationScope.(effect: Transmission.Signal) -> Unit>() + + @PublishedApi + internal val effectHandlerRegistry = + mutableMapOf, suspend CommunicationScope.(effect: Transmission.Effect) -> Unit>() + + @PublishedApi + internal inline fun registerSignal(noinline lambda: suspend CommunicationScope.(signal: T) -> Unit) { + signalHandlerRegistry[T::class] = + lambda as suspend CommunicationScope.(Transmission.Signal) -> Unit + } + + @PublishedApi + internal inline fun registerEffect(noinline lambda: suspend CommunicationScope.(effect: T) -> Unit) { + effectHandlerRegistry[T::class] = + lambda as suspend CommunicationScope.(Transmission.Effect) -> Unit + } + +} From 9375114aa8bfd259be6cd7ea97f2296527838be9 Mon Sep 17 00:00:00 2001 From: Yigit Ozgumus Date: Mon, 29 Jul 2024 13:39:08 +0300 Subject: [PATCH 3/3] Update sample usage and router tests --- .../colorpicker/ColorPickerTransformer.kt | 39 ++++++++--------- .../features/input/InputTransformer.kt | 25 +++++------ .../multioutput/MultiOutputTransformer.kt | 33 +++++++------- .../features/output/OutputTransformer.kt | 43 +++++++++---------- .../transmission/transformer/Transformer.kt | 17 +++----- .../transformer/FakeTransformer.kt | 34 ++++++++------- 6 files changed, 90 insertions(+), 101 deletions(-) diff --git a/sample/src/main/java/com/trendyol/transmission/features/colorpicker/ColorPickerTransformer.kt b/sample/src/main/java/com/trendyol/transmission/features/colorpicker/ColorPickerTransformer.kt index 89e2573..0209361 100644 --- a/sample/src/main/java/com/trendyol/transmission/features/colorpicker/ColorPickerTransformer.kt +++ b/sample/src/main/java/com/trendyol/transmission/features/colorpicker/ColorPickerTransformer.kt @@ -4,8 +4,10 @@ import com.trendyol.transmission.DefaultDispatcher import com.trendyol.transmission.features.multioutput.multiOutputTransformerIdentity import com.trendyol.transmission.transformer.Transformer import com.trendyol.transmission.transformer.dataholder.buildDataHolder -import com.trendyol.transmission.transformer.handler.buildGenericEffectHandler -import com.trendyol.transmission.transformer.handler.buildGenericSignalHandler +import com.trendyol.transmission.transformer.handler.HandlerRegistry +import com.trendyol.transmission.transformer.handler.handlerRegistry +import com.trendyol.transmission.transformer.handler.registerEffect +import com.trendyol.transmission.transformer.handler.registerSignal import com.trendyol.transmission.transformer.request.buildDataContract import com.trendyol.transmission.transformer.request.createIdentity import com.trendyol.transmission.ui.ColorPickerUiState @@ -20,27 +22,20 @@ class ColorPickerTransformer @Inject constructor( private val holder = buildDataHolder(ColorPickerUiState(), holderContract) - override val signalHandler = buildGenericSignalHandler { signal -> - when (signal) { - is ColorPickerSignal.SelectColor -> { - holder.update { it.copy(selectedColorIndex = signal.index) } - publish( - ColorPickerEffect.BackgroundColorUpdate(signal.selectedColor.copy(alpha = 0.1f)) - ) - send( - effect = ColorPickerEffect.SelectedColorUpdate(signal.selectedColor), - identity = multiOutputTransformerIdentity - ) - } + override val handlerRegistry: HandlerRegistry = handlerRegistry { + registerSignal { signal -> + holder.update { it.copy(selectedColorIndex = signal.index) } + publish( + ColorPickerEffect.BackgroundColorUpdate(signal.selectedColor.copy(alpha = 0.1f)) + ) + send( + effect = ColorPickerEffect.SelectedColorUpdate(signal.selectedColor), + identity = multiOutputTransformerIdentity + ) } - } - - override val effectHandler = buildGenericEffectHandler { effect -> - when (effect) { - is ColorPickerEffect.BackgroundColorUpdate -> { - holder.update { - it.copy(backgroundColor = effect.color) - } + registerEffect { effect -> + holder.update { + it.copy(backgroundColor = effect.color) } } } diff --git a/sample/src/main/java/com/trendyol/transmission/features/input/InputTransformer.kt b/sample/src/main/java/com/trendyol/transmission/features/input/InputTransformer.kt index 4841422..074b208 100644 --- a/sample/src/main/java/com/trendyol/transmission/features/input/InputTransformer.kt +++ b/sample/src/main/java/com/trendyol/transmission/features/input/InputTransformer.kt @@ -4,8 +4,10 @@ import com.trendyol.transmission.DefaultDispatcher import com.trendyol.transmission.features.colorpicker.ColorPickerEffect import com.trendyol.transmission.transformer.Transformer import com.trendyol.transmission.transformer.dataholder.buildDataHolder -import com.trendyol.transmission.transformer.handler.buildGenericEffectHandler -import com.trendyol.transmission.transformer.handler.buildTypedSignalHandler +import com.trendyol.transmission.transformer.handler.HandlerRegistry +import com.trendyol.transmission.transformer.handler.handlerRegistry +import com.trendyol.transmission.transformer.handler.registerEffect +import com.trendyol.transmission.transformer.handler.registerSignal import com.trendyol.transmission.transformer.request.buildComputationContract import com.trendyol.transmission.transformer.request.buildComputationContractWithArgs import com.trendyol.transmission.transformer.request.buildDataContract @@ -32,20 +34,13 @@ class InputTransformer @Inject constructor( } } - override val signalHandler = buildTypedSignalHandler { signal -> - when (signal) { - is InputSignal.InputUpdate -> { - holder.update { it.copy(writtenText = signal.value) } - publish(effect = InputEffect.InputUpdate(signal.value)) - } + override val handlerRegistry: HandlerRegistry = handlerRegistry { + registerSignal { signal -> + holder.update { it.copy(writtenText = signal.value) } + publish(effect = InputEffect.InputUpdate(signal.value)) } - } - - override val effectHandler = buildGenericEffectHandler { effect -> - when (effect) { - is ColorPickerEffect.BackgroundColorUpdate -> { - holder.update { it.copy(backgroundColor = effect.color) } - } + registerEffect { effect -> + holder.update { it.copy(backgroundColor = effect.color) } } } diff --git a/sample/src/main/java/com/trendyol/transmission/features/multioutput/MultiOutputTransformer.kt b/sample/src/main/java/com/trendyol/transmission/features/multioutput/MultiOutputTransformer.kt index a3a0ee7..729f233 100644 --- a/sample/src/main/java/com/trendyol/transmission/features/multioutput/MultiOutputTransformer.kt +++ b/sample/src/main/java/com/trendyol/transmission/features/multioutput/MultiOutputTransformer.kt @@ -6,7 +6,9 @@ import com.trendyol.transmission.features.input.InputEffect import com.trendyol.transmission.features.output.OutputTransformer import com.trendyol.transmission.transformer.Transformer import com.trendyol.transmission.transformer.dataholder.buildDataHolder -import com.trendyol.transmission.transformer.handler.buildGenericEffectHandler +import com.trendyol.transmission.transformer.handler.HandlerRegistry +import com.trendyol.transmission.transformer.handler.handlerRegistry +import com.trendyol.transmission.transformer.handler.registerEffect import com.trendyol.transmission.transformer.request.createIdentity import com.trendyol.transmission.ui.MultiOutputUiState import kotlinx.coroutines.CoroutineDispatcher @@ -20,23 +22,20 @@ class MultiOutputTransformer @Inject constructor( private val holder = buildDataHolder(MultiOutputUiState()) - override val effectHandler = buildGenericEffectHandler { effect -> - when (effect) { - is InputEffect.InputUpdate -> { - holder.update { it.copy(writtenUppercaseText = effect.value.uppercase()) } - val result = compute(OutputTransformer.outputCalculationContract) - holder.update { - it.copy(writtenUppercaseText = it.writtenUppercaseText + " ${result?.result}") - } - } - - is ColorPickerEffect.BackgroundColorUpdate -> { - holder.update { it.copy(backgroundColor = effect.color) } - } - - is ColorPickerEffect.SelectedColorUpdate -> { - holder.update { it.copy(selectedColor = effect.color) } + override val handlerRegistry: HandlerRegistry = handlerRegistry { + registerEffect { effect -> + holder.update { it.copy(writtenUppercaseText = effect.value.uppercase()) } + val result = compute(OutputTransformer.outputCalculationContract) + holder.update { + it.copy(writtenUppercaseText = it.writtenUppercaseText + " ${result?.result}") } } + registerEffect { effect -> + holder.update { it.copy(backgroundColor = effect.color) } + } + registerEffect { effect -> + holder.update { it.copy(selectedColor = effect.color) } + } } + } diff --git a/sample/src/main/java/com/trendyol/transmission/features/output/OutputTransformer.kt b/sample/src/main/java/com/trendyol/transmission/features/output/OutputTransformer.kt index 39d6bff..4e13738 100644 --- a/sample/src/main/java/com/trendyol/transmission/features/output/OutputTransformer.kt +++ b/sample/src/main/java/com/trendyol/transmission/features/output/OutputTransformer.kt @@ -9,7 +9,9 @@ import com.trendyol.transmission.features.input.InputEffect import com.trendyol.transmission.features.input.InputTransformer import com.trendyol.transmission.transformer.Transformer import com.trendyol.transmission.transformer.dataholder.buildDataHolder -import com.trendyol.transmission.transformer.handler.buildGenericEffectHandler +import com.trendyol.transmission.transformer.handler.HandlerRegistry +import com.trendyol.transmission.transformer.handler.handlerRegistry +import com.trendyol.transmission.transformer.handler.registerEffect import com.trendyol.transmission.transformer.request.buildComputationContract import com.trendyol.transmission.transformer.request.buildExecutionContract import com.trendyol.transmission.transformer.request.computation.registerComputation @@ -47,28 +49,25 @@ class OutputTransformer @Inject constructor( } } - override val effectHandler = buildGenericEffectHandler { effect -> - when (effect) { - is InputEffect.InputUpdate -> { - holder.update { it.copy(outputText = effect.value) } - delay(3.seconds) - val selectedColor = getData(ColorPickerTransformer.holderContract) - selectedColor ?: return@buildGenericEffectHandler - holder.update { - it.copy(outputText = it.outputText + " and Selected color index is ${selectedColor.selectedColorIndex}") - } - delay(1.seconds) - send( - effect = ColorPickerEffect.BackgroundColorUpdate(holder2.getValue().backgroundColor), - identity = colorPickerIdentity - ) - execute(outputExecutionContract) - publish(effect = RouterEffect(holder.getValue())) - } - - is ColorPickerEffect.BackgroundColorUpdate -> { - holder.update { it.copy(backgroundColor = effect.color) } + override val handlerRegistry: HandlerRegistry = handlerRegistry { + registerEffect { effect -> + holder.update { it.copy(outputText = effect.value) } + delay(3.seconds) + val selectedColor = getData(ColorPickerTransformer.holderContract) + selectedColor ?: return@registerEffect + holder.update { + it.copy(outputText = it.outputText + " and Selected color index is ${selectedColor.selectedColorIndex}") } + delay(1.seconds) + send( + effect = ColorPickerEffect.BackgroundColorUpdate(holder2.getValue().backgroundColor), + identity = colorPickerIdentity + ) + execute(outputExecutionContract) + publish(effect = RouterEffect(holder.getValue())) + } + registerEffect { effect -> + holder.update { it.copy(backgroundColor = effect.color) } } } diff --git a/transmission/src/main/java/com/trendyol/transmission/transformer/Transformer.kt b/transmission/src/main/java/com/trendyol/transmission/transformer/Transformer.kt index acb91e3..a4205e3 100644 --- a/transmission/src/main/java/com/trendyol/transmission/transformer/Transformer.kt +++ b/transmission/src/main/java/com/trendyol/transmission/transformer/Transformer.kt @@ -5,6 +5,7 @@ import com.trendyol.transmission.effect.EffectWrapper import com.trendyol.transmission.effect.RouterEffect import com.trendyol.transmission.transformer.handler.CommunicationScope import com.trendyol.transmission.transformer.handler.EffectHandler +import com.trendyol.transmission.transformer.handler.HandlerRegistry import com.trendyol.transmission.transformer.handler.SignalHandler import com.trendyol.transmission.transformer.request.Contract import com.trendyol.transmission.transformer.request.Query @@ -42,8 +43,7 @@ open class Transformer( internal val dataChannel: Channel = Channel(capacity = Channel.BUFFERED) internal val storage = TransformerStorage() - open val signalHandler: SignalHandler? = null - open val effectHandler: EffectHandler? = null + protected open val handlerRegistry : HandlerRegistry? = null protected val executionRegistry: ExecutionRegistry by lazy { ExecutionRegistry(this) } protected val computationRegistry: ComputationRegistry by lazy { ComputationRegistry(this) } @@ -60,10 +60,8 @@ open class Transformer( fun startSignalCollection(incoming: SharedFlow) { transformerScope.launch { incoming.collect { - signalHandler?.apply { - currentSignalProcessing = launch { - communicationScope.onSignal(it) - } + currentSignalProcessing = launch { + handlerRegistry?.signalHandlerRegistry?.get(it::class)?.invoke(communicationScope, it) } } } @@ -84,10 +82,9 @@ open class Transformer( .filter { it.identity == null || it.identity == internalIdentity } .map { it.effect } .collect { - effectHandler?.apply { - currentEffectProcessing = launch { - communicationScope.onEffect(it) - } + currentEffectProcessing = launch { + handlerRegistry?.effectHandlerRegistry?.get(it::class) + ?.invoke(communicationScope, it) } } } diff --git a/transmission/src/test/kotlin/com/trendyol/transmission/transformer/FakeTransformer.kt b/transmission/src/test/kotlin/com/trendyol/transmission/transformer/FakeTransformer.kt index 4707f49..19d8d68 100644 --- a/transmission/src/test/kotlin/com/trendyol/transmission/transformer/FakeTransformer.kt +++ b/transmission/src/test/kotlin/com/trendyol/transmission/transformer/FakeTransformer.kt @@ -4,25 +4,29 @@ import com.trendyol.transmission.Transmission import com.trendyol.transmission.effect.RouterEffect import com.trendyol.transmission.transformer.data.TestData import com.trendyol.transmission.transformer.data.TestEffect +import com.trendyol.transmission.transformer.data.TestSignal import com.trendyol.transmission.transformer.dataholder.buildDataHolder -import com.trendyol.transmission.transformer.handler.buildGenericEffectHandler -import com.trendyol.transmission.transformer.handler.buildGenericSignalHandler +import com.trendyol.transmission.transformer.handler.HandlerRegistry +import com.trendyol.transmission.transformer.handler.handlerRegistry +import com.trendyol.transmission.transformer.handler.registerEffect +import com.trendyol.transmission.transformer.handler.registerSignal import kotlinx.coroutines.CoroutineDispatcher open class FakeTransformer(dispatcher: CoroutineDispatcher) : Transformer(dispatcher) { - val signalList = mutableListOf() - val effectList = mutableListOf() + val signalList = mutableListOf() + val effectList = mutableListOf() - private val holder = buildDataHolder(null) + private val holder = buildDataHolder(null) - override val signalHandler = buildGenericSignalHandler { signal -> - signalList.add(signal) - publish(TestEffect) - publish(RouterEffect("")) - holder.update { TestData("update with ${this@FakeTransformer.javaClass.simpleName}") } - } - - override val effectHandler = buildGenericEffectHandler { effect -> - effectList.add(effect) - } + override val handlerRegistry: HandlerRegistry = handlerRegistry { + registerSignal { signal -> + signalList.add(signal) + publish(TestEffect) + publish(RouterEffect("")) + holder.update { TestData("update with ${this@FakeTransformer.javaClass.simpleName}") } + } + registerEffect { effect -> + effectList.add(effect) + } + } }