Skip to content

Commit f47954b

Browse files
committed
feat(mps-sync-plugin): show synchronization progress
1 parent 4a6694f commit f47954b

File tree

5 files changed

+54
-5
lines changed

5 files changed

+54
-5
lines changed

bulk-model-sync-lib/src/commonMain/kotlin/org/modelix/model/sync/bulk/ModelSynchronizer.kt

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,26 @@ class ModelSynchronizer(
4242
) {
4343
private val nodesToRemove: MutableSet<IWritableNode> = HashSet()
4444
private val pendingReferences: MutableList<PendingReference> = ArrayList()
45+
private val syncStack = ArrayList<IReadableNode>()
46+
47+
fun getCurrentSyncStack(): List<IReadableNode> = syncStack.toList()
48+
49+
private inline fun <R> withPushSyncStack(element: IReadableNode, body: () -> R): R {
50+
syncStack.add(element)
51+
try {
52+
return body()
53+
} finally {
54+
syncStack.removeLast()
55+
}
56+
}
4557

4658
private fun <R> runSafe(body: () -> R): Result<R> {
4759
return if (onException == null) {
4860
Result.success(body())
4961
} else {
5062
runCatching(body)
51-
.onFailure { LOG.error(it) { "Ignoring exception during synchronization" } }
5263
.onFailure { onException(it) }
64+
.onFailure { LOG.error(it) { "Ignoring exception during synchronization" } }
5365
}
5466
}
5567

@@ -81,7 +93,11 @@ class ModelSynchronizer(
8193
LOG.debug { "Synchronization finished." }
8294
}
8395

84-
private fun synchronizeNode(sourceNode: IReadableNode, targetNode: IWritableNode, forceSyncDescendants: Boolean) {
96+
private fun synchronizeNode(
97+
sourceNode: IReadableNode,
98+
targetNode: IWritableNode,
99+
forceSyncDescendants: Boolean,
100+
): Unit = withPushSyncStack(sourceNode) {
85101
nodeAssociation.associate(sourceNode, targetNode)
86102
if (forceSyncDescendants || filter.needsSynchronization(sourceNode)) {
87103
LOG.trace { "Synchronizing changed node. sourceNode = $sourceNode" }

mps-sync-plugin3/src/main/kotlin/org/modelix/mps/sync3/BindingWorker.kt

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import org.modelix.model.api.IReadableNode
1717
import org.modelix.model.api.IWritableNode
1818
import org.modelix.model.api.NodeReference
1919
import org.modelix.model.api.TreePointer
20+
import org.modelix.model.api.getName
2021
import org.modelix.model.api.getOriginalReference
2122
import org.modelix.model.api.getRootNode
2223
import org.modelix.model.client2.runWrite
@@ -52,6 +53,8 @@ class BindingWorker(
5253
private var syncJob: Job? = null
5354
private var syncToServerTask: ValidatingJob? = null
5455
private var invalidatingListener: MyInvalidatingListener? = null
56+
private var activeSynchronizer: ModelSynchronizer? = null
57+
private var previousSyncStack: List<IReadableNode> = emptyList()
5558

5659
private val repository: SRepository get() = mpsProject.repository
5760
private suspend fun client() = serverConnection.getClient()
@@ -75,6 +78,28 @@ class BindingWorker(
7578
invalidatingListener = null
7679
}
7780

81+
private fun ModelSynchronizer.executeSync() {
82+
try {
83+
activeSynchronizer = this
84+
synchronize()
85+
} finally {
86+
activeSynchronizer = null
87+
previousSyncStack = emptyList()
88+
}
89+
}
90+
91+
fun getSyncProgress(): String? {
92+
val synchronizer = activeSynchronizer ?: return null
93+
val current = synchronizer.getCurrentSyncStack()
94+
val previous = previousSyncStack
95+
previousSyncStack = current
96+
val firstChange = current.zip(previous).indexOfFirst { it.first != it.second }
97+
val busyPath = current.take(firstChange + 1)
98+
return busyPath.joinToString(" > ") {
99+
it.getName() ?: it.tryGetConcept()?.getShortName() ?: it.getNodeReference().serialize()
100+
}
101+
}
102+
78103
private suspend fun checkInSync(): String? {
79104
check(activated.get()) { "Binding is deactivated" }
80105
val version = lastSyncedVersion.flush()?.getOrThrow()
@@ -250,7 +275,7 @@ class BindingWorker(
250275
sourceMask = MPSProjectSyncMask(listOf(mpsProject), false),
251276
targetMask = MPSProjectSyncMask(listOf(mpsProject), true),
252277
onException = { getMPSListener().synchronizationErrorHappened() },
253-
).synchronize()
278+
).executeSync()
254279
}
255280
}
256281
}
@@ -310,7 +335,7 @@ class BindingWorker(
310335
nodeAssociation = nodeAssociation,
311336
sourceMask = MPSProjectSyncMask(listOf(mpsProject), true),
312337
targetMask = MPSProjectSyncMask(listOf(mpsProject), false),
313-
).synchronize()
338+
).executeSync()
314339
}
315340
}
316341
}

mps-sync-plugin3/src/main/kotlin/org/modelix/mps/sync3/IModelSyncService.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,6 @@ interface IBinding : Closeable {
7575
suspend fun flushIfEnabled(): IVersion?
7676
fun forceSync(push: Boolean)
7777
fun getCurrentVersion(): IVersion?
78+
79+
fun getSyncProgress(): String?
7880
}

mps-sync-plugin3/src/main/kotlin/org/modelix/mps/sync3/ModelSyncService.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,10 @@ class ModelSyncService(val project: Project) :
345345
return workers[id]?.getCurrentVersion()
346346
}
347347

348+
override fun getSyncProgress(): String? {
349+
return workers[id]?.getSyncProgress()
350+
}
351+
348352
private fun getService(): ModelSyncService = this@ModelSyncService
349353

350354
override fun equals(other: Any?): Boolean {

mps-sync-plugin3/src/main/kotlin/org/modelix/mps/sync3/ui/ModelSyncStatusWidget.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,9 @@ class ModelSyncStatusWidget(val project: Project) : CustomStatusBarWidget, Statu
242242
return "Click to log in"
243243
}
244244
}
245-
result = binding.getCurrentVersion()?.getContentHash()?.let { "Synchronized: ${it.take(5)}" } ?: result
245+
result = binding.getSyncProgress()?.let { "Synchronizing: $it" }
246+
?: binding.getCurrentVersion()?.getContentHash()?.let { "Synchronized: ${it.take(5)}" }
247+
?: result
246248
}
247249
}
248250
}

0 commit comments

Comments
 (0)