Skip to content

Commit

Permalink
feat: Cache Orchestrator by orchestratorId (#100)
Browse files Browse the repository at this point in the history
  • Loading branch information
devxb authored Mar 23, 2024
1 parent 8ee7c5c commit 0d856bd
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 36 deletions.
76 changes: 40 additions & 36 deletions src/main/kotlin/org/rooftop/netx/engine/OrchestrateChain.kt
Original file line number Diff line number Diff line change
Expand Up @@ -84,25 +84,27 @@ class OrchestrateChain<OriginReq : Any, T : Any, V : Any> private constructor(
val nextCommitOrchestrateListener = getCommitOrchestrateListener(function)
val nextRollbackOrchestrateListener = getRollbackOrchestrateListener<V, S>(rollback)

val nextOrchestrateChain = OrchestrateChain(
orchestratorId,
orchestrateSequence + 1,
chainContainer,
nextCommitOrchestrateListener,
nextRollbackOrchestrateListener,
this,
)
this.nextOrchestrateChain = nextOrchestrateChain
val firstOrchestrateChain = nextOrchestrateChain.initOrchestrateListeners()
return OrchestratorCache.cache(orchestratorId) {
val nextOrchestrateChain = OrchestrateChain(
orchestratorId,
orchestrateSequence + 1,
chainContainer,
nextCommitOrchestrateListener,
nextRollbackOrchestrateListener,
this,
)
this.nextOrchestrateChain = nextOrchestrateChain
val firstOrchestrateChain = nextOrchestrateChain.initOrchestrateListeners()

return OrchestratorManager(
transactionManager = chainContainer.transactionManager,
codec = chainContainer.codec,
orchestratorId = orchestratorId,
resultHolder = chainContainer.resultHolder,
orchestrateListener = firstOrchestrateChain.orchestrateListener,
rollbackOrchestrateListener = firstOrchestrateChain.rollbackOrchestrateListener,
)
return@cache OrchestratorManager<OriginReq, S>(
transactionManager = chainContainer.transactionManager,
codec = chainContainer.codec,
orchestratorId = orchestratorId,
resultHolder = chainContainer.resultHolder,
orchestrateListener = firstOrchestrateChain.orchestrateListener,
rollbackOrchestrateListener = firstOrchestrateChain.rollbackOrchestrateListener,
)
}
}

private fun <T : Any, V : Any> getCommitOrchestrateListener(function: OrchestrateFunction<T, V>) =
Expand Down Expand Up @@ -136,26 +138,28 @@ class OrchestrateChain<OriginReq : Any, T : Any, V : Any> private constructor(
val nextJoinOrchestrateListener = getMonoCommitOrchestrateListener(function)
val nextRollbackOrchestrateListener = getMonoRollbackOrchestrateListener<V, S>(rollback)

val nextOrchestrateChain = OrchestrateChain(
orchestratorId,
orchestrateSequence + 1,
chainContainer,
nextJoinOrchestrateListener,
nextRollbackOrchestrateListener,
this,
)
this.nextOrchestrateChain = nextOrchestrateChain
return OrchestratorCache.cache(orchestratorId) {
val nextOrchestrateChain = OrchestrateChain(
orchestratorId,
orchestrateSequence + 1,
chainContainer,
nextJoinOrchestrateListener,
nextRollbackOrchestrateListener,
this,
)
this.nextOrchestrateChain = nextOrchestrateChain

val firstOrchestrateChain = nextOrchestrateChain.initOrchestrateListeners()
val firstOrchestrateChain = nextOrchestrateChain.initOrchestrateListeners()

return OrchestratorManager(
transactionManager = chainContainer.transactionManager,
codec = chainContainer.codec,
orchestratorId = orchestratorId,
resultHolder = chainContainer.resultHolder,
orchestrateListener = firstOrchestrateChain.orchestrateListener,
rollbackOrchestrateListener = firstOrchestrateChain.rollbackOrchestrateListener,
)
return@cache OrchestratorManager<OriginReq, S>(
transactionManager = chainContainer.transactionManager,
codec = chainContainer.codec,
orchestratorId = orchestratorId,
resultHolder = chainContainer.resultHolder,
orchestrateListener = firstOrchestrateChain.orchestrateListener,
rollbackOrchestrateListener = firstOrchestrateChain.rollbackOrchestrateListener,
)
}
}

@Suppress("UNCHECKED_CAST")
Expand Down
25 changes: 25 additions & 0 deletions src/main/kotlin/org/rooftop/netx/engine/OrchestratorCache.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.rooftop.netx.engine

import org.rooftop.netx.api.Orchestrator

internal object OrchestratorCache {

private val cache: MutableMap<String, Orchestrator<*, *>> = mutableMapOf()

@Suppress("UNCHECKED_CAST")
internal fun <T : Any, V : Any> cache(
key: String,
behavior: () -> Orchestrator<*, *>,
): Orchestrator<T, V> {
if (cache.contains(key)) {
return cache[key] as Orchestrator<T, V>
}
synchronized(key) {
if (cache.contains(key)) {
return cache[key] as Orchestrator<T, V>
}
cache[key] = behavior.invoke()
return cache[key] as Orchestrator<T, V>
}
}
}
54 changes: 54 additions & 0 deletions src/test/kotlin/org/rooftop/netx/engine/OrchestratorCacheTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package org.rooftop.netx.engine

import io.kotest.core.annotation.DisplayName
import io.kotest.core.spec.style.DescribeSpec
import io.kotest.matchers.equals.shouldBeEqual
import io.kotest.matchers.equals.shouldNotBeEqual
import org.rooftop.netx.api.Orchestrator
import org.rooftop.netx.factory.OrchestratorFactory
import org.rooftop.netx.meta.EnableDistributedTransaction
import org.rooftop.netx.redis.RedisContainer
import org.springframework.test.context.ContextConfiguration
import org.springframework.test.context.TestPropertySource

@EnableDistributedTransaction
@DisplayName("OrchestratorCache 클래스의")
@ContextConfiguration(classes = [RedisContainer::class])
@TestPropertySource("classpath:application.properties")
internal class OrchestratorCacheTest(
private val orchestratorFactory: OrchestratorFactory,
) : DescribeSpec({

describe("cache 메소드는") {
context("같은 orchestratorId를 가진 Orchestrator 를 생성하려하면,") {
val expected = orchestratorFactory.createIntOrchestrator("same")

it("동일한 Orchestrator 를 반환한다.") {
val sameOrchestrator = orchestratorFactory.createIntOrchestrator("same")

expected shouldBeEqual sameOrchestrator
}
}

context("다른 orchestratorId를 가진 Orchestrator 를 생성하려하면,") {
val expected = orchestratorFactory.createIntOrchestrator("same")

it("동일하지 않은 Orchestrator 를 반환한다.") {
val notSameOrchestrator = orchestratorFactory.createIntOrchestrator("notSame")

expected shouldNotBeEqual notSameOrchestrator
}
}
}

}) {

companion object {

private fun OrchestratorFactory.createIntOrchestrator(orchestratorId: String): Orchestrator<Int, Int> {
return this.create<Int>(orchestratorId)
.start({ it + 1 })
.commit({ it + 1 })
}
}
}

0 comments on commit 0d856bd

Please sign in to comment.