Skip to content

Commit 1327513

Browse files
committed
fix(model-client): implemented LightModelClient.getArea().addListener
1 parent c2df489 commit 1327513

File tree

1 file changed

+43
-13
lines changed

1 file changed

+43
-13
lines changed

light-model-client/src/commonMain/kotlin/org/modelix/client/light/LightModelClient.kt

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ import io.ktor.client.engine.*
55
import io.ktor.client.plugins.websocket.*
66
import kotlinx.coroutines.delay
77
import org.modelix.model.api.*
8-
import org.modelix.model.area.IArea
9-
import org.modelix.model.area.IAreaListener
10-
import org.modelix.model.area.IAreaReference
8+
import org.modelix.model.area.*
119
import org.modelix.model.server.api.*
1210
import kotlin.jvm.JvmStatic
1311
import kotlin.time.Duration
@@ -18,13 +16,14 @@ private const val TEMP_ID_PREFIX = "tmp-"
1816

1917
class LightModelClient internal constructor(
2018
val connection: IConnection,
21-
val transactionManager: ITransactionManager,
19+
private val transactionManager: ITransactionManager,
2220
val autoFilterNonLoadedNodes: Boolean,
2321
val debugName: String = ""
2422
) {
2523

2624
private val nodes: MutableMap<NodeId, NodeData> = HashMap()
2725
private val area = Area()
26+
private var areaListeners: Set<IAreaListener> = emptySet()
2827
private var repositoryId: String? = null
2928
private var lastMergedVersionHash: String? = null
3029
private val pendingOperations: MutableList<OperationData> = ArrayList()
@@ -50,6 +49,18 @@ class LightModelClient internal constructor(
5049
LOG.error(ex) { "Failed to process message: $message" }
5150
}
5251
}
52+
transactionManager.afterWrite {
53+
val changes = object : IAreaChangeList {
54+
override fun visitChanges(visitor: (IAreaChangeEvent) -> Boolean) {}
55+
}
56+
areaListeners.forEach { l ->
57+
try {
58+
l.areaChanged(changes)
59+
} catch (ex: Exception) {
60+
LOG.error(ex) { "" }
61+
}
62+
}
63+
}
5364
}
5465

5566
fun dispose() {
@@ -611,11 +622,11 @@ class LightModelClient internal constructor(
611622
}
612623

613624
override fun addListener(l: IAreaListener) {
614-
TODO("Not yet implemented")
625+
areaListeners += l
615626
}
616627

617628
override fun removeListener(l: IAreaListener) {
618-
TODO("Not yet implemented")
629+
areaListeners -= l
619630
}
620631
}
621632

@@ -645,16 +656,18 @@ class LightModelClient internal constructor(
645656
}
646657
}
647658

648-
interface ITransactionManager {
659+
internal interface ITransactionManager {
649660
fun <T> requiresRead(body: () -> T): T
650661
fun <T> requiresWrite(body: () -> T): T
651662
fun <T> runRead(body: () -> T): T
652663
fun <T> runWrite(body: () -> T): T
653664
fun canRead(): Boolean
654665
fun canWrite(): Boolean
666+
fun afterWrite(listener: () -> Unit)
655667
}
656668

657-
class ReadWriteLockTransactionManager : ITransactionManager {
669+
private class ReadWriteLockTransactionManager : ITransactionManager {
670+
private var writeListener: (() -> Unit)? = null
658671
private val lock = ReadWriteLock()
659672
override fun <T> requiresRead(body: ()->T): T {
660673
if (!lock.canRead()) throw IllegalStateException("Not in a read transaction")
@@ -665,12 +678,30 @@ class ReadWriteLockTransactionManager : ITransactionManager {
665678
return body()
666679
}
667680
override fun <T> runRead(body: () -> T): T = lock.runRead(body)
668-
override fun <T> runWrite(body: () -> T): T = lock.runWrite(body)
681+
override fun <T> runWrite(body: () -> T): T {
682+
if (canWrite()) {
683+
return body()
684+
} else {
685+
try {
686+
return lock.runWrite(body)
687+
} finally {
688+
try {
689+
writeListener?.invoke()
690+
} catch (ex: Exception) {
691+
mu.KotlinLogging.logger { }.error(ex) { "Exception in write listener" }
692+
}
693+
}
694+
}
695+
}
669696
override fun canRead(): Boolean = lock.canRead()
670697
override fun canWrite(): Boolean = lock.canWrite()
698+
override fun afterWrite(listener: () -> Unit) {
699+
if (writeListener != null) throw IllegalStateException("Only one listener is supported")
700+
writeListener = listener
701+
}
671702
}
672703

673-
class AutoTransactions(val delegate: ITransactionManager) : ITransactionManager by delegate {
704+
private class AutoTransactions(val delegate: ITransactionManager) : ITransactionManager by delegate {
674705
override fun <T> requiresRead(body: () -> T): T {
675706
return if (canRead()) {
676707
body()
@@ -726,10 +757,9 @@ abstract class LightModelClientBuilder {
726757
return this
727758
}
728759
fun autoTransactions(): LightModelClientBuilder {
729-
transactionManager = AutoTransactions(transactionManager)
730-
return this
760+
return transactionManager(AutoTransactions(transactionManager))
731761
}
732-
fun transactionManager(tm: ITransactionManager): LightModelClientBuilder {
762+
private fun transactionManager(tm: ITransactionManager): LightModelClientBuilder {
733763
this.transactionManager = tm
734764
return this
735765
}

0 commit comments

Comments
 (0)