Skip to content

Commit 5de2880

Browse files
authored
Merge pull request #672 from modelix/fix/bulk-sync-pull-caching
MODELIX-740 bulk-model-sync should not cache pull result from model-server
2 parents 2f7a632 + 6ecbff6 commit 5de2880

File tree

6 files changed

+157
-76
lines changed

6 files changed

+157
-76
lines changed

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

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import org.modelix.model.sync.bulk.gradle.config.ServerSource
2929
import org.modelix.model.sync.bulk.gradle.config.ServerTarget
3030
import org.modelix.model.sync.bulk.gradle.config.SyncDirection
3131
import org.modelix.model.sync.bulk.gradle.tasks.ExportFromModelServer
32+
import org.modelix.model.sync.bulk.gradle.tasks.GetRevisionInfo
3233
import org.modelix.model.sync.bulk.gradle.tasks.ImportIntoModelServer
3334
import org.modelix.model.sync.bulk.gradle.tasks.ValidateSyncSettings
3435
import java.io.File
@@ -77,7 +78,7 @@ class ModelSyncGradlePlugin : Plugin<Project> {
7778
val baseDir = project.layout.buildDirectory.dir("model-sync").get().asFile.apply { mkdirs() }
7879
val jsonDir = baseDir.resolve(syncDirection.name).apply { mkdir() }
7980
val sourceTask = when (syncDirection.source) {
80-
is LocalSource -> registerTasksForLocalSource(syncDirection, project, previousTask, jsonDir)
81+
is LocalSource -> registerTasksForLocalSource(syncDirection, previousTask, jsonDir)
8182
is ServerSource -> registerTasksForServerSource(syncDirection, project, previousTask, jsonDir)
8283
else -> error("Unknown sync direction source")
8384
}
@@ -95,15 +96,32 @@ class ModelSyncGradlePlugin : Plugin<Project> {
9596
jsonDir: File,
9697
): TaskProvider<*> {
9798
val serverSource = syncDirection.source as ServerSource
99+
val revisionFile = jsonDir.resolve(".modelix_revision").also { it.createNewFile() }
98100

99-
val name = "${syncDirection.name}ExportFromModelServer"
100-
val exportFromModelServer = project.tasks.register(name, ExportFromModelServer::class.java) {
101+
val getRevisionInfo = project.tasks.register(
102+
"${syncDirection.name}GetRevisionInfo",
103+
GetRevisionInfo::class.java,
104+
) {
101105
it.dependsOn(previousTask)
102-
it.outputDir.set(jsonDir)
103-
it.url.set(serverSource.url)
106+
107+
it.serverUrl.set(serverSource.url)
108+
it.revision.set(serverSource.revision)
104109
it.repositoryId.set(serverSource.repositoryId)
105110
it.branchName.set(serverSource.branchName)
106-
it.revision.set(serverSource.revision)
111+
it.revisionFile.set(revisionFile)
112+
113+
it.outputs.upToDateWhen { serverSource.revision != null }
114+
}
115+
116+
val exportFromModelServer = project.tasks.register(
117+
"${syncDirection.name}ExportFromModelServer",
118+
ExportFromModelServer::class.java,
119+
) {
120+
it.dependsOn(getRevisionInfo)
121+
it.url.set(serverSource.url)
122+
it.repositoryId.set(serverSource.repositoryId)
123+
it.revisionFile.set(revisionFile)
124+
it.outputDir.set(jsonDir)
107125
it.includedModules.set(syncDirection.includedModules)
108126
it.includedModulePrefixes.set(syncDirection.includedModulePrefixes)
109127
it.requestTimeoutSeconds.set(serverSource.requestTimeoutSeconds)
@@ -113,7 +131,6 @@ class ModelSyncGradlePlugin : Plugin<Project> {
113131

114132
private fun registerTasksForLocalSource(
115133
syncDirection: SyncDirection,
116-
project: Project,
117134
previousTask: TaskProvider<*>,
118135
jsonDir: File,
119136
): TaskProvider<*> {
@@ -212,10 +229,6 @@ class ModelSyncGradlePlugin : Plugin<Project> {
212229
return project.layout.buildDirectory.dir("model-sync").get().asFile
213230
}
214231

215-
private fun getDependenciesDir(project: Project): File {
216-
return getBaseDir(project).resolve("dependencies")
217-
}
218-
219232
private fun readModelixCoreVersion(): String? {
220233
val resources = javaClass.classLoader.getResources("modelix.core.version.properties") ?: return null
221234
if (resources.hasMoreElements()) {

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

Lines changed: 30 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -19,66 +19,68 @@ package org.modelix.model.sync.bulk.gradle.tasks
1919
import kotlinx.coroutines.runBlocking
2020
import org.gradle.api.DefaultTask
2121
import org.gradle.api.file.DirectoryProperty
22-
import org.gradle.api.model.ObjectFactory
22+
import org.gradle.api.file.RegularFileProperty
2323
import org.gradle.api.provider.Property
2424
import org.gradle.api.provider.SetProperty
2525
import org.gradle.api.tasks.Input
26+
import org.gradle.api.tasks.InputFile
2627
import org.gradle.api.tasks.Optional
2728
import org.gradle.api.tasks.OutputDirectory
2829
import org.gradle.api.tasks.TaskAction
2930
import org.modelix.model.api.BuiltinLanguages
3031
import org.modelix.model.api.INode
3132
import org.modelix.model.api.PBranch
3233
import org.modelix.model.api.getRootNode
33-
import org.modelix.model.client2.ModelClientV2
3434
import org.modelix.model.client2.ModelClientV2PlatformSpecificBuilder
35-
import org.modelix.model.lazy.BranchReference
3635
import org.modelix.model.lazy.RepositoryId
3736
import org.modelix.model.sync.bulk.ModelExporter
3837
import org.modelix.model.sync.bulk.isModuleIncluded
39-
import javax.inject.Inject
4038
import kotlin.time.Duration.Companion.seconds
4139

42-
abstract class ExportFromModelServer @Inject constructor(of: ObjectFactory) : DefaultTask() {
40+
abstract class ExportFromModelServer : DefaultTask() {
4341

44-
@Input
45-
val url: Property<String> = of.property(String::class.java)
42+
@get:Input
43+
abstract val url: Property<String>
4644

47-
@Input
48-
@Optional
49-
val repositoryId: Property<String> = of.property(String::class.java)
45+
@get:Input
46+
@get:Optional
47+
abstract val repositoryId: Property<String>
5048

51-
@Input
52-
@Optional
53-
val branchName: Property<String> = of.property(String::class.java)
49+
@get:InputFile
50+
abstract val revisionFile: RegularFileProperty
5451

55-
@Input
56-
@Optional
57-
val revision: Property<String> = of.property(String::class.java)
52+
@get:OutputDirectory
53+
abstract val outputDir: DirectoryProperty
5854

59-
@OutputDirectory
60-
val outputDir: DirectoryProperty = of.directoryProperty()
55+
@get:Input
56+
abstract val includedModules: SetProperty<String>
6157

62-
@Input
63-
val includedModules: SetProperty<String> = of.setProperty(String::class.java)
58+
@get:Input
59+
abstract val includedModulePrefixes: SetProperty<String>
6460

65-
@Input
66-
val includedModulePrefixes: SetProperty<String> = of.setProperty(String::class.java)
67-
68-
@Input
69-
val requestTimeoutSeconds: Property<Int> = of.property(Int::class.java)
70-
71-
private fun getBranchReference(): BranchReference = RepositoryId(repositoryId.get()).getBranchReference(branchName.get())
61+
@get:Input
62+
abstract val requestTimeoutSeconds: Property<Int>
7263

7364
@TaskAction
7465
fun export() = runBlocking {
7566
val modelClient = ModelClientV2PlatformSpecificBuilder()
7667
.url(url.get())
7768
.requestTimeout(requestTimeoutSeconds.get().seconds)
7869
.build()
70+
71+
val revision = revisionFile.get().asFile.readText()
72+
7973
modelClient.use { client ->
8074
client.init()
81-
val branch = loadDataAsBranch(client)
75+
val version = if (repositoryId.isPresent) {
76+
client.loadVersion(RepositoryId(repositoryId.get()), revision, null)
77+
} else {
78+
logger.warn("Specifying a repositoryId will be mandatory in the future.")
79+
client.loadVersion(revision, null)
80+
}
81+
82+
val branch = PBranch(version.getTree(), client.getIdGenerator())
83+
8284
branch.runRead {
8385
val root = branch.getRootNode()
8486
logger.info("Got root node: {}", root)
@@ -93,16 +95,6 @@ abstract class ExportFromModelServer @Inject constructor(of: ObjectFactory) : De
9395
}
9496
}
9597

96-
private suspend fun loadDataAsBranch(client: ModelClientV2): PBranch {
97-
val version = if (revision.isPresent) {
98-
client.loadVersion(revision.get(), null)
99-
} else {
100-
client.pull(getBranchReference(), null)
101-
}
102-
val branch = PBranch(version.getTree(), client.getIdGenerator())
103-
return branch
104-
}
105-
10698
private fun getIncludedModules(root: INode): Iterable<INode> {
10799
val nameRole = BuiltinLanguages.jetbrains_mps_lang_core.INamedConcept.name
108100

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright (c) 2024.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.modelix.model.sync.bulk.gradle.tasks
18+
19+
import kotlinx.coroutines.runBlocking
20+
import org.gradle.api.DefaultTask
21+
import org.gradle.api.file.RegularFileProperty
22+
import org.gradle.api.provider.Property
23+
import org.gradle.api.tasks.Input
24+
import org.gradle.api.tasks.Optional
25+
import org.gradle.api.tasks.OutputFile
26+
import org.gradle.api.tasks.TaskAction
27+
import org.modelix.model.client2.ModelClientV2
28+
import org.modelix.model.lazy.RepositoryId
29+
30+
/**
31+
* Determines which revision needs to be pulled from the model server.
32+
* The determined revision is written to [revisionFile].
33+
*/
34+
abstract class GetRevisionInfo : DefaultTask() {
35+
36+
@get:Input
37+
abstract val serverUrl: Property<String>
38+
39+
@get:Input
40+
abstract val repositoryId: Property<String>
41+
42+
@get:Input
43+
abstract val branchName: Property<String>
44+
45+
@get:Input
46+
@get:Optional
47+
abstract val revision: Property<String>
48+
49+
@get:OutputFile
50+
abstract val revisionFile: RegularFileProperty
51+
52+
@TaskAction
53+
fun getRevisionInfo() {
54+
val revision = determineRevision()
55+
logger.info("Revision to be synced: $revision")
56+
revisionFile.get().asFile.writeText(revision)
57+
}
58+
59+
private fun determineRevision(): String {
60+
if (revision.isPresent) {
61+
return revision.get()
62+
}
63+
64+
logger.info("Pulling versionHash from server...")
65+
val modelClient = ModelClientV2.builder().url(serverUrl.get()).build()
66+
val branchRef = RepositoryId(repositoryId.get()).getBranchReference(branchName.get())
67+
68+
return runBlocking {
69+
modelClient.use {
70+
it.init()
71+
it.pullHash(branchRef)
72+
}
73+
}
74+
}
75+
}

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

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ package org.modelix.model.sync.bulk.gradle.tasks
1919
import kotlinx.coroutines.runBlocking
2020
import org.gradle.api.DefaultTask
2121
import org.gradle.api.file.DirectoryProperty
22-
import org.gradle.api.model.ObjectFactory
2322
import org.gradle.api.provider.MapProperty
2423
import org.gradle.api.provider.Property
2524
import org.gradle.api.provider.SetProperty
@@ -39,38 +38,37 @@ import org.modelix.model.operations.OTBranch
3938
import org.modelix.model.sync.bulk.ModelImporter
4039
import org.modelix.model.sync.bulk.importFilesAsRootChildren
4140
import org.modelix.model.sync.bulk.isModuleIncluded
42-
import javax.inject.Inject
4341
import kotlin.time.Duration.Companion.seconds
4442

45-
abstract class ImportIntoModelServer @Inject constructor(of: ObjectFactory) : DefaultTask() {
43+
abstract class ImportIntoModelServer : DefaultTask() {
4644

47-
@InputDirectory
48-
@PathSensitive(PathSensitivity.RELATIVE)
49-
val inputDir: DirectoryProperty = of.directoryProperty()
45+
@get:InputDirectory
46+
@get:PathSensitive(PathSensitivity.RELATIVE)
47+
abstract val inputDir: DirectoryProperty
5048

51-
@Input
52-
val repositoryId: Property<String> = of.property(String::class.java)
49+
@get:Input
50+
abstract val repositoryId: Property<String>
5351

54-
@Input
55-
val branchName: Property<String> = of.property(String::class.java)
52+
@get:Input
53+
abstract val branchName: Property<String>
5654

57-
@Input
58-
val url: Property<String> = of.property(String::class.java)
55+
@get:Input
56+
abstract val url: Property<String>
5957

60-
@Input
61-
val includedModules: SetProperty<String> = of.setProperty(String::class.java)
58+
@get:Input
59+
abstract val includedModules: SetProperty<String>
6260

63-
@Input
64-
val includedModulePrefixes: SetProperty<String> = of.setProperty(String::class.java)
61+
@get:Input
62+
abstract val includedModulePrefixes: SetProperty<String>
6563

66-
@Input
67-
val continueOnError: Property<Boolean> = of.property(Boolean::class.java)
64+
@get:Input
65+
abstract val continueOnError: Property<Boolean>
6866

69-
@Input
70-
val requestTimeoutSeconds: Property<Int> = of.property(Int::class.java)
67+
@get:Input
68+
abstract val requestTimeoutSeconds: Property<Int>
7169

72-
@Input
73-
val metaProperties: MapProperty<String, String> = of.mapProperty(String::class.java, String::class.java)
70+
@get:Input
71+
abstract val metaProperties: MapProperty<String, String>
7472

7573
@TaskAction
7674
fun import() = runBlocking {

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package org.modelix.model.sync.bulk.gradle.tasks
1818

1919
import org.gradle.api.DefaultTask
20-
import org.gradle.api.model.ObjectFactory
2120
import org.gradle.api.provider.Property
2221
import org.gradle.api.tasks.CacheableTask
2322
import org.gradle.api.tasks.Input
@@ -28,18 +27,17 @@ import org.modelix.model.sync.bulk.gradle.config.ModelSyncGradleSettings
2827
import org.modelix.model.sync.bulk.gradle.config.ServerSource
2928
import org.modelix.model.sync.bulk.gradle.config.ServerTarget
3029
import org.modelix.model.sync.bulk.gradle.config.SyncDirection
31-
import javax.inject.Inject
3230

3331
/**
3432
* Instead of throwing exceptions for single configuration errors,
3533
* this task collects all configuration errors and puts them into a single exception,
3634
* so the user can see all steps that must be taken at a glance.
3735
*/
3836
@CacheableTask
39-
abstract class ValidateSyncSettings @Inject constructor(of: ObjectFactory) : DefaultTask() {
37+
abstract class ValidateSyncSettings : DefaultTask() {
4038

41-
@Input
42-
val settings: Property<ModelSyncGradleSettings> = of.property(ModelSyncGradleSettings::class.java)
39+
@get:Input
40+
abstract val settings: Property<ModelSyncGradleSettings>
4341

4442
private val errorMsgBuilder = StringBuilder()
4543

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ mpsBuild {
115115
|===
116116

117117
=== ServerSource/-Target configuration
118+
[WARNING]
119+
--
120+
In the future you will be required to specify a `repositoryId` along the`revision`.
121+
--
118122
[%header, cols="1,1,2"]
119123
|===
120124
|setting
@@ -153,6 +157,7 @@ Only available in ServerTarget.
153157

154158
|===
155159

160+
156161
== Example
157162

158163
[source,kotlin]

0 commit comments

Comments
 (0)