@@ -5,9 +5,7 @@ import io.ktor.client.engine.*
5
5
import io.ktor.client.plugins.websocket.*
6
6
import kotlinx.coroutines.delay
7
7
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.*
11
9
import org.modelix.model.server.api.*
12
10
import kotlin.jvm.JvmStatic
13
11
import kotlin.time.Duration
@@ -18,13 +16,14 @@ private const val TEMP_ID_PREFIX = "tmp-"
18
16
19
17
class LightModelClient internal constructor(
20
18
val connection : IConnection ,
21
- val transactionManager : ITransactionManager ,
19
+ private val transactionManager : ITransactionManager ,
22
20
val autoFilterNonLoadedNodes : Boolean ,
23
21
val debugName : String = " "
24
22
) {
25
23
26
24
private val nodes: MutableMap <NodeId , NodeData > = HashMap ()
27
25
private val area = Area ()
26
+ private var areaListeners: Set <IAreaListener > = emptySet()
28
27
private var repositoryId: String? = null
29
28
private var lastMergedVersionHash: String? = null
30
29
private val pendingOperations: MutableList <OperationData > = ArrayList ()
@@ -50,6 +49,18 @@ class LightModelClient internal constructor(
50
49
LOG .error(ex) { " Failed to process message: $message " }
51
50
}
52
51
}
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
+ }
53
64
}
54
65
55
66
fun dispose () {
@@ -611,11 +622,11 @@ class LightModelClient internal constructor(
611
622
}
612
623
613
624
override fun addListener (l : IAreaListener ) {
614
- TODO ( " Not yet implemented " )
625
+ areaListeners + = l
615
626
}
616
627
617
628
override fun removeListener (l : IAreaListener ) {
618
- TODO ( " Not yet implemented " )
629
+ areaListeners - = l
619
630
}
620
631
}
621
632
@@ -645,16 +656,18 @@ class LightModelClient internal constructor(
645
656
}
646
657
}
647
658
648
- interface ITransactionManager {
659
+ internal interface ITransactionManager {
649
660
fun <T > requiresRead (body : () -> T ): T
650
661
fun <T > requiresWrite (body : () -> T ): T
651
662
fun <T > runRead (body : () -> T ): T
652
663
fun <T > runWrite (body : () -> T ): T
653
664
fun canRead (): Boolean
654
665
fun canWrite (): Boolean
666
+ fun afterWrite (listener : () -> Unit )
655
667
}
656
668
657
- class ReadWriteLockTransactionManager : ITransactionManager {
669
+ private class ReadWriteLockTransactionManager : ITransactionManager {
670
+ private var writeListener: (() -> Unit )? = null
658
671
private val lock = ReadWriteLock ()
659
672
override fun <T > requiresRead (body : ()-> T ): T {
660
673
if (! lock.canRead()) throw IllegalStateException (" Not in a read transaction" )
@@ -665,12 +678,30 @@ class ReadWriteLockTransactionManager : ITransactionManager {
665
678
return body()
666
679
}
667
680
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
+ }
669
696
override fun canRead (): Boolean = lock.canRead()
670
697
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
+ }
671
702
}
672
703
673
- class AutoTransactions (val delegate : ITransactionManager ) : ITransactionManager by delegate {
704
+ private class AutoTransactions (val delegate : ITransactionManager ) : ITransactionManager by delegate {
674
705
override fun <T > requiresRead (body : () -> T ): T {
675
706
return if (canRead()) {
676
707
body()
@@ -726,10 +757,9 @@ abstract class LightModelClientBuilder {
726
757
return this
727
758
}
728
759
fun autoTransactions (): LightModelClientBuilder {
729
- transactionManager = AutoTransactions (transactionManager)
730
- return this
760
+ return transactionManager(AutoTransactions (transactionManager))
731
761
}
732
- fun transactionManager (tm : ITransactionManager ): LightModelClientBuilder {
762
+ private fun transactionManager (tm : ITransactionManager ): LightModelClientBuilder {
733
763
this .transactionManager = tm
734
764
return this
735
765
}
0 commit comments