Skip to content

Commit 995af79

Browse files
committed
feat(bulk-model-sync-gradle): add continueOnError option
With the new option, the sync can ignore errors encountered during syncing instead of immediately terminating. This is some sort of graceful degradation at the cost of potentially resulting in an inconsistent sync. continueOnError will be implemented for local targets later on. To inform users about this, a warning message is printed if continueOnError is used with a local target.
1 parent 4cbd113 commit 995af79

File tree

5 files changed

+51
-8
lines changed

5 files changed

+51
-8
lines changed

bulk-model-sync-gradle/src/main/kotlin/org/modelix/model/sync/bulk/gradle/ModelSyncGradlePlugin.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ class ModelSyncGradlePlugin : Plugin<Project> {
177177
it.branchName.set(serverTarget.branchName)
178178
it.includedModules.set(syncDirection.includedModules)
179179
it.includedModulePrefixes.set(syncDirection.includedModulePrefixes)
180+
it.continueOnError.set(syncDirection.continueOnError)
180181
}
181182

182183
project.tasks.register("runSync${syncDirection.name.replaceFirstChar { it.uppercaseChar() }}") {
@@ -191,6 +192,10 @@ class ModelSyncGradlePlugin : Plugin<Project> {
191192
previousTask: TaskProvider<*>,
192193
jsonDir: File,
193194
) {
195+
if (syncDirection.continueOnError) {
196+
println("Continue on error is currently not supported for local targets")
197+
}
198+
194199
val localTarget = syncDirection.target as LocalTarget
195200

196201
val antScript = jsonDir.resolve("build.xml")

bulk-model-sync-gradle/src/main/kotlin/org/modelix/model/sync/bulk/gradle/config/ModelSyncGradleSettings.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ data class SyncDirection(
4343
internal val registeredLanguages: Set<ILanguage> = mutableSetOf(),
4444
internal val includedModulePrefixes: Set<String> = mutableSetOf(),
4545
internal var mpsDebugEnabled: Boolean = false,
46+
internal var continueOnError: Boolean = false,
4647
) {
4748
fun fromModelServer(action: Action<ServerSource>) {
4849
val endpoint = ServerSource()
@@ -79,6 +80,10 @@ data class SyncDirection(
7980
fun registerLanguage(language: ILanguage) {
8081
(registeredLanguages as MutableSet).add(language)
8182
}
83+
84+
fun enableContinueOnError(state: Boolean) {
85+
continueOnError = state
86+
}
8287
}
8388

8489
interface SyncEndpoint {

bulk-model-sync-gradle/src/main/kotlin/org/modelix/model/sync/bulk/gradle/tasks/ImportIntoModelServer.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ abstract class ImportIntoModelServer @Inject constructor(of: ObjectFactory) : De
6262
@Input
6363
val includedModulePrefixes: SetProperty<String> = of.setProperty(String::class.java)
6464

65+
@Input
66+
val continueOnError: Property<Boolean> = of.property(Boolean::class.java)
67+
6568
@TaskAction
6669
fun import() {
6770
registeredLanguages.get().forEach {
@@ -83,7 +86,7 @@ abstract class ImportIntoModelServer @Inject constructor(of: ObjectFactory) : De
8386
client.runWrite(branchRef) { rootNode ->
8487
logger.info("Got root node: {}", rootNode)
8588
logger.info("Importing...")
86-
ModelImporter(rootNode).importFilesAsRootChildren(files)
89+
ModelImporter(rootNode, continueOnError.get()).importFilesAsRootChildren(files)
8790
logger.info("Import finished")
8891
}
8992
}

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

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ import kotlin.jvm.JvmName
3838
*
3939
* @param root the root node to be updated
4040
*/
41-
class ModelImporter(private val root: INode) {
41+
class ModelImporter(private val root: INode, private val continueOnError: Boolean) {
4242

4343
private val originalIdToExisting: MutableMap<String, INode> = mutableMapOf()
4444
private val postponedReferences = ArrayList<() -> Unit>()
@@ -47,6 +47,22 @@ class ModelImporter(private val root: INode) {
4747
private var currentNodeProgress = 0
4848
private val logger = KotlinLogging.logger {}
4949

50+
// For MPS / Java compatibility, where a default value does not work. Can be dropped once the MPS solution is
51+
// updated to the constructor with two arguments.
52+
constructor(root: INode) : this(root, false)
53+
54+
private fun doAndPotentiallyContinueOnErrors(block: () -> Unit) {
55+
try {
56+
block()
57+
} catch (e: Exception) {
58+
if (continueOnError) {
59+
logger.error(e) { "Ignoring this error and continuing as requested" }
60+
} else {
61+
throw e
62+
}
63+
}
64+
}
65+
5066
/**
5167
* Incrementally updates this importers root based on the provided [ModelData] specification.
5268
*
@@ -68,10 +84,18 @@ class ModelImporter(private val root: INode) {
6884
syncNode(root, data.root)
6985

7086
logger.info { "Synchronizing references..." }
71-
postponedReferences.forEach { it.invoke() }
87+
postponedReferences.forEach {
88+
doAndPotentiallyContinueOnErrors {
89+
it.invoke()
90+
}
91+
}
7292

7393
logger.info { "Removing extra nodes..." }
74-
nodesToRemove.forEach { it.remove() }
94+
nodesToRemove.forEach {
95+
doAndPotentiallyContinueOnErrors {
96+
it.remove()
97+
}
98+
}
7599

76100
logger.info { "Synchronization finished." }
77101
}
@@ -83,10 +107,12 @@ class ModelImporter(private val root: INode) {
83107
currentNodeProgress += 1
84108
// print instead of log, so that the progress line can be overwritten by the carriage return
85109
print("\r($currentNodeProgress / $numExpectedNodes) Synchronizing nodes... ")
86-
syncProperties(node, data)
87-
syncChildren(node, data)
88-
INodeResolutionScope.runWithAdditionalScope(node.getArea()) {
89-
syncReferences(node, data)
110+
doAndPotentiallyContinueOnErrors {
111+
syncProperties(node, data)
112+
syncChildren(node, data)
113+
INodeResolutionScope.runWithAdditionalScope(node.getArea()) {
114+
syncReferences(node, data)
115+
}
90116
}
91117
}
92118

docs/global/modules/core/pages/reference/component-bulk-model-sync-gradle.adoc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ This means that only a minimal amount of write operations is used to update the
7474
|`includeModulesByPrefix`
7575
|String
7676
|Includes all modules, whose fully qualified name starts with the given prefix, in the synchronisation process.
77+
78+
|`enableContinueOnError`
79+
|Boolean
80+
|If the sync encounters an error, simply log it and continue instead of terminating. This most likely results in an incomplete sync result. Defaults to `false`.
7781
|===
7882

7983
=== LocalSource/-Target configuration

0 commit comments

Comments
 (0)