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 cb10994..d0440d0 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 @@ -10,9 +10,12 @@ 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.request.buildComputationContract +import com.trendyol.transmission.transformer.request.buildExecutionContract import com.trendyol.transmission.transformer.request.computation.registerComputation +import com.trendyol.transmission.transformer.request.execution.registerExecution import com.trendyol.transmission.ui.ColorPickerUiState import com.trendyol.transmission.ui.OutputUiState +import com.trendyol.transmission.ui.theme.Pink80 import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.delay import javax.inject.Inject @@ -35,6 +38,10 @@ class OutputTransformer @Inject constructor( val result = Random.nextInt(5, 15) * Random.nextInt(5, 15) OutputCalculationResult("result is $result with ($writtenOutput) and $data") } + registerExecution(outputExecutionContract) { + delay(4.seconds) + communicationScope.publish(ColorPickerEffect.BackgroundColorUpdate(Pink80)) + } } override val effectHandler = buildGenericEffectHandler { effect -> @@ -52,6 +59,7 @@ class OutputTransformer @Inject constructor( effect = ColorPickerEffect.BackgroundColorUpdate(holder2.getValue().backgroundColor), to = ColorPickerTransformer::class ) + execute(outputExecutionContract) publish(effect = RouterEffect(holder.getValue())) } @@ -64,5 +72,7 @@ class OutputTransformer @Inject constructor( companion object { val outputCalculationContract = buildComputationContract("OutputCalculationResult") + val outputExecutionContract = + buildExecutionContract("outputExecutionContract") } } diff --git a/sample/src/test/java/com/trendyol/transmission/features/colorpicker/ColorPickerTransformerTest.kt b/sample/src/test/java/com/trendyol/transmission/features/colorpicker/ColorPickerTransformerTest.kt index 6f0aa9d..d25568f 100644 --- a/sample/src/test/java/com/trendyol/transmission/features/colorpicker/ColorPickerTransformerTest.kt +++ b/sample/src/test/java/com/trendyol/transmission/features/colorpicker/ColorPickerTransformerTest.kt @@ -67,5 +67,4 @@ class ColorPickerTransformerTest { assertTrue { effectStream.last().effect is ColorPickerEffect.SelectedColorUpdate } } } - } diff --git a/transmission-test/src/main/java/com/yigitozgumus/transmissiontesting/TestRouter.kt b/transmission-test/src/main/java/com/yigitozgumus/transmissiontesting/TestRouter.kt index b695d21..6451ff6 100644 --- a/transmission-test/src/main/java/com/yigitozgumus/transmissiontesting/TestRouter.kt +++ b/transmission-test/src/main/java/com/yigitozgumus/transmissiontesting/TestRouter.kt @@ -19,7 +19,7 @@ import kotlinx.coroutines.launch internal class TestRouter( private val registry: RegistryScopeImpl, private val transformer: Transformer, - private val dispatcher: CoroutineDispatcher + dispatcher: CoroutineDispatcher ) { private val testScope = CoroutineScope(dispatcher) @@ -83,8 +83,8 @@ internal class TestRouter( is Query.Computation -> processComputationQuery(query) is Query.Data -> processDataQuery(query) is Query.ComputationWithArgs<*> -> processComputationQueryWithArgs(query) - is Query.Execution -> TODO() - is Query.ExecutionWithArgs<*> -> TODO() + is Query.Execution -> {} + is Query.ExecutionWithArgs<*> -> {} } } diff --git a/transmission/src/main/java/com/trendyol/transmission/router/RequestDelegate.kt b/transmission/src/main/java/com/trendyol/transmission/router/RequestDelegate.kt index 170e741..6089589 100644 --- a/transmission/src/main/java/com/trendyol/transmission/router/RequestDelegate.kt +++ b/transmission/src/main/java/com/trendyol/transmission/router/RequestDelegate.kt @@ -6,7 +6,6 @@ import com.trendyol.transmission.transformer.request.Contract import com.trendyol.transmission.transformer.request.Query import com.trendyol.transmission.transformer.request.QueryResult import com.trendyol.transmission.transformer.request.RequestHandler -import com.trendyol.transmission.transformer.request.computation.ComputationOwner import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.async import kotlinx.coroutines.channels.Channel @@ -45,8 +44,8 @@ internal class RequestDelegate( is Query.Computation -> processComputationQuery(query) is Query.Data -> processDataQuery(query) is Query.ComputationWithArgs<*> -> processComputationQueryWithArgs(query) - is Query.Execution -> TODO() - is Query.ExecutionWithArgs<*> -> TODO() + is Query.Execution -> processExecution(query) + is Query.ExecutionWithArgs<*> -> processExecutionWithArgs(query) } } @@ -116,6 +115,23 @@ internal class RequestDelegate( } } + private fun processExecution( + query: Query.Execution + ) = queryScope.launch { + val executionHolder = routerRef.transformerSet + .find { it.storage.hasExecution(query.key) } + executionHolder?.storage?.getExecutionByKey(query.key) + ?.execute(executionHolder.communicationScope) + } + + private fun processExecutionWithArgs(query: Query.ExecutionWithArgs) = + queryScope.launch { + val executionHolder = routerRef.transformerSet + .find { it.storage.hasExecution(query.key) } + executionHolder?.storage?.getExecutionByKey(query.key) + ?.execute(executionHolder.communicationScope, query.args) + } + override suspend fun , D : Transmission.Data> getData(contract: C): D? { outGoingQuery.trySend( Query.Data(sender = routerRef.routerName, key = contract.key) @@ -162,15 +178,25 @@ internal class RequestDelegate( .first().data } - override suspend fun execute(contract: C, invalidate: Boolean) { - TODO("Not yet implemented") + override suspend fun execute(contract: C) { + outGoingQuery.trySend( + Query.Execution( + sender = routerRef.routerName, + key = contract.key, + ) + ) } override suspend fun , A : Any> execute( contract: C, - args: A, - invalidate: Boolean + args: A ) { - TODO("Not yet implemented") + outGoingQuery.trySend( + Query.ExecutionWithArgs( + sender = routerRef.routerName, + key = contract.key, + args = args, + ) + ) } } diff --git a/transmission/src/main/java/com/trendyol/transmission/transformer/CommunicationScopeBuilder.kt b/transmission/src/main/java/com/trendyol/transmission/transformer/CommunicationScopeBuilder.kt index 81f65d1..48e0d3b 100644 --- a/transmission/src/main/java/com/trendyol/transmission/transformer/CommunicationScopeBuilder.kt +++ b/transmission/src/main/java/com/trendyol/transmission/transformer/CommunicationScopeBuilder.kt @@ -45,15 +45,14 @@ internal class CommunicationScopeBuilder( return requestDelegate.interactor.compute(contract, args, invalidate) } - override suspend fun execute(contract: C, invalidate: Boolean) { - TODO("Not yet implemented") + override suspend fun execute(contract: C) { + requestDelegate.interactor.execute(contract) } override suspend fun , A : Any> execute( contract: C, - args: A, - invalidate: Boolean + args: A ) { - TODO("Not yet implemented") + requestDelegate.interactor.execute(contract, args) } } diff --git a/transmission/src/main/java/com/trendyol/transmission/transformer/TransformerStorage.kt b/transmission/src/main/java/com/trendyol/transmission/transformer/TransformerStorage.kt index 3fd8f14..9e01d97 100644 --- a/transmission/src/main/java/com/trendyol/transmission/transformer/TransformerStorage.kt +++ b/transmission/src/main/java/com/trendyol/transmission/transformer/TransformerStorage.kt @@ -4,6 +4,7 @@ import com.trendyol.transmission.Transmission import com.trendyol.transmission.identifier import com.trendyol.transmission.transformer.dataholder.HolderState import com.trendyol.transmission.transformer.request.computation.ComputationOwner +import com.trendyol.transmission.transformer.request.execution.ExecutionOwner import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.update @@ -17,6 +18,9 @@ internal class TransformerStorage { private val internalComputationMap: MutableMap = mutableMapOf() + private val internalExecutionMap: MutableMap = + mutableMapOf() + fun isHolderStateInitialized(): Boolean { return internalTransmissionHolderSet is HolderState.Initialized } @@ -34,7 +38,6 @@ internal class TransformerStorage { } fun updateHolderDataReferenceToTrack(dataHolderToTrack: String) { - internalTransmissionHolderSet = when (internalTransmissionHolderSet) { is HolderState.Initialized -> { val currentSet = (internalTransmissionHolderSet as HolderState.Initialized).valueSet @@ -57,18 +60,37 @@ internal class TransformerStorage { internalComputationMap[key] = delegate } + fun registerExecution(key: String, delegate: ExecutionOwner) { + require(!internalExecutionMap.containsKey(key)) { + "Multiple executions with the same key is not allowed: $key" + } + internalExecutionMap[key] = delegate + } + fun hasComputation(type: String): Boolean { return internalComputationMap.containsKey(type) } + fun hasExecution(type: String): Boolean { + return internalExecutionMap.containsKey(type) + } + fun getComputationByKey(type: String): ComputationOwner.Default? { return internalComputationMap[type] as? ComputationOwner.Default } - fun getComputationByKey(type: String): ComputationOwner.WithArgs? { + fun getExecutionByKey(type: String): ExecutionOwner.Default? { + return internalExecutionMap[type] as? ExecutionOwner.Default + } + + fun getComputationByKey(type: String): ComputationOwner.WithArgs? { return internalComputationMap[type] as? ComputationOwner.WithArgs } + fun getExecutionByKey(type: String): ExecutionOwner.WithArgs? { + return internalExecutionMap[type] as? ExecutionOwner.WithArgs + } + fun getHolderDataByKey(key: String): Transmission.Data? { return holderDataReference.value[key] } diff --git a/transmission/src/main/java/com/trendyol/transmission/transformer/request/TransformerRequestDelegate.kt b/transmission/src/main/java/com/trendyol/transmission/transformer/request/TransformerRequestDelegate.kt index 6d56841..55329b0 100644 --- a/transmission/src/main/java/com/trendyol/transmission/transformer/request/TransformerRequestDelegate.kt +++ b/transmission/src/main/java/com/trendyol/transmission/transformer/request/TransformerRequestDelegate.kt @@ -59,16 +59,26 @@ internal class TransformerRequestDelegate(scope: CoroutineScope, identifier: Str .first().data } - override suspend fun execute(contract: C, invalidate: Boolean) { - TODO("Not yet implemented") + override suspend fun execute(contract: C) { + outGoingQuery.trySend( + Query.Execution( + sender = identifier, + key = contract.key, + ) + ) } override suspend fun , A : Any> execute( contract: C, - args: A, - invalidate: Boolean + args: A ) { - TODO("Not yet implemented") + outGoingQuery.trySend( + Query.ExecutionWithArgs( + sender = identifier, + key = contract.key, + args = args, + ) + ) } } } diff --git a/transmission/src/main/java/com/trendyol/transmission/transformer/request/execution/ExecutionBuilder.kt b/transmission/src/main/java/com/trendyol/transmission/transformer/request/execution/ExecutionBuilder.kt new file mode 100644 index 0000000..01c581e --- /dev/null +++ b/transmission/src/main/java/com/trendyol/transmission/transformer/request/execution/ExecutionBuilder.kt @@ -0,0 +1,29 @@ +package com.trendyol.transmission.transformer.request.execution + +import com.trendyol.transmission.transformer.Transformer +import com.trendyol.transmission.transformer.request.RequestHandler + +class ExecutionBuilder { + + fun buildWith( + key: String, + transformer: Transformer, + execution: suspend RequestHandler.() -> Unit + ) { + transformer.storage.registerExecution( + key = key, + delegate = ExecutionDelegate(execution) + ) + } + + fun buildWith( + key: String, + transformer: Transformer, + execution: suspend RequestHandler.(args: A) -> Unit + ) { + transformer.storage.registerExecution( + key = key, + delegate = ExecutionDelegateWithArgs(execution) + ) + } +} diff --git a/transmission/src/main/java/com/trendyol/transmission/transformer/request/execution/ExecutionDelegateImpl.kt b/transmission/src/main/java/com/trendyol/transmission/transformer/request/execution/ExecutionDelegateImpl.kt new file mode 100644 index 0000000..5399219 --- /dev/null +++ b/transmission/src/main/java/com/trendyol/transmission/transformer/request/execution/ExecutionDelegateImpl.kt @@ -0,0 +1,21 @@ +package com.trendyol.transmission.transformer.request.execution + +import com.trendyol.transmission.transformer.request.RequestHandler + +internal class ExecutionDelegate( + private val execution: suspend RequestHandler.() -> Unit, +) : ExecutionOwner.Default { + + override suspend fun execute(scope: RequestHandler) { + execution.invoke(scope) + } +} + +internal class ExecutionDelegateWithArgs( + private val execution: suspend RequestHandler.(args: A) -> Unit, +) : ExecutionOwner.WithArgs { + + override suspend fun execute(scope: RequestHandler, args: A) { + execution(scope, args) + } +} diff --git a/transmission/src/main/java/com/trendyol/transmission/transformer/request/execution/ExecutionExt.kt b/transmission/src/main/java/com/trendyol/transmission/transformer/request/execution/ExecutionExt.kt new file mode 100644 index 0000000..03b215a --- /dev/null +++ b/transmission/src/main/java/com/trendyol/transmission/transformer/request/execution/ExecutionExt.kt @@ -0,0 +1,37 @@ +package com.trendyol.transmission.transformer.request.execution + +import com.trendyol.transmission.Transmission +import com.trendyol.transmission.transformer.Transformer +import com.trendyol.transmission.transformer.request.Contract +import com.trendyol.transmission.transformer.request.RequestHandler + +/** + * Throws [IllegalArgumentException] when multiple executions with the same key + * are defined inside the [Transformer]. + * + * Adds a execution to [Transformer] to be queried that returns Unit. + * Can be queried using [RequestHandler.execute] + * @param execution execution to get the result [Transmission.Data] + */ +fun Transformer.registerExecution( + contract: C, + execution: suspend RequestHandler.() -> Unit, +) { + ExecutionBuilder().buildWith(contract.key, this, execution) +} + +/** + * Throws [IllegalArgumentException] when multiple executions with the same key + * are defined inside the [Transformer]. + * + * Adds a execution to [Transformer] to be queried. This execution accepts any class as Argument + * that returns Unit. + * Can be queried using [RequestHandler.execute] + * @param execution execution to get the result [Transmission.Data] + */ +fun , A : Any> Transformer.registerExecution( + contract: C, + execution: suspend RequestHandler.(args: A) -> Unit, +) { + ExecutionBuilder().buildWith(contract.key, this, execution) +} diff --git a/transmission/src/main/java/com/trendyol/transmission/transformer/request/execution/ExecutionOwner.kt b/transmission/src/main/java/com/trendyol/transmission/transformer/request/execution/ExecutionOwner.kt new file mode 100644 index 0000000..179f916 --- /dev/null +++ b/transmission/src/main/java/com/trendyol/transmission/transformer/request/execution/ExecutionOwner.kt @@ -0,0 +1,14 @@ +package com.trendyol.transmission.transformer.request.execution + +import com.trendyol.transmission.transformer.request.RequestHandler + +internal sealed interface ExecutionOwner { + + interface WithArgs : ExecutionOwner { + suspend fun execute(scope: RequestHandler, args: A) + } + + interface Default : ExecutionOwner { + suspend fun execute(scope: RequestHandler) + } +}