@@ -27,6 +27,7 @@ import org.modelix.authorization.checkPermission
27
27
import org.modelix.authorization.getUserName
28
28
import org.modelix.authorization.hasPermission
29
29
import org.modelix.authorization.requiresLogin
30
+ import org.modelix.model.ObjectDeltaFilter
30
31
import org.modelix.model.api.IBranch
31
32
import org.modelix.model.api.PBranch
32
33
import org.modelix.model.api.TreeAsBranch
@@ -110,6 +111,7 @@ class ModelReplicationServer(
110
111
repository : String ,
111
112
branch : String ,
112
113
lastKnown : String? ,
114
+ filter : String? ,
113
115
) {
114
116
checkPermission(ModelServerPermissionSchema .repository(repository).branch(branch).pull)
115
117
val branchRef = repositoryId(repository).getBranchReference(branch)
@@ -118,13 +120,20 @@ class ModelReplicationServer(
118
120
val versionHash = runRead {
119
121
repositoriesManager.getVersionHash(branchRef) ? : throw BranchNotFoundException (branchRef)
120
122
}
121
- call.respondDelta(RepositoryId (repository), versionHash, lastKnown)
123
+ call.respondDelta(RepositoryId (repository), versionHash, parseFilter(filter, lastKnown))
124
+ }
125
+
126
+ private fun parseFilter (filterAsJson : String? , lastKnown : String? ): ObjectDeltaFilter {
127
+ return (filterAsJson?.let { ObjectDeltaFilter .fromJson(it) } ? : ObjectDeltaFilter ()).let {
128
+ if (lastKnown == null ) it else it.copy(knownVersions = it.knownVersions + lastKnown)
129
+ }
122
130
}
123
131
124
132
override suspend fun RoutingContext.getRepositoryBranchV1 (
125
133
repository : String ,
126
134
branch : String ,
127
135
lastKnown : String? ,
136
+ filter : String? ,
128
137
) {
129
138
checkPermission(ModelServerPermissionSchema .repository(repository).branch(branch).pull)
130
139
val branchRef = repositoryId(repository).getBranchReference(branch)
@@ -189,7 +198,7 @@ class ModelReplicationServer(
189
198
legacyGlobalStorage ? : false ,
190
199
)
191
200
}
192
- call.respondDelta(RepositoryId (repository), initialVersion.getContentHash(), null )
201
+ call.respondDelta(RepositoryId (repository), initialVersion.getContentHash(), ObjectDeltaFilter () )
193
202
}
194
203
195
204
override suspend fun RoutingContext.deleteRepository (repository : String ) {
@@ -223,7 +232,7 @@ class ModelReplicationServer(
223
232
val mergedHash = runWrite {
224
233
repositoriesManager.mergeChanges(branchRef, deltaFromClient.versionHash)
225
234
}
226
- call.respondDelta(RepositoryId (repository), mergedHash, deltaFromClient.versionHash)
235
+ call.respondDelta(RepositoryId (repository), mergedHash, ObjectDeltaFilter ( deltaFromClient.versionHash) )
227
236
}
228
237
229
238
override suspend fun RoutingContext.pollRepositoryBranch (
@@ -234,7 +243,7 @@ class ModelReplicationServer(
234
243
checkPermission(ModelServerPermissionSchema .repository(repository).branch(branch).pull)
235
244
val branchRef = repositoryId(repository).getBranchReference(branch)
236
245
val newVersionHash = repositoriesManager.pollVersionHash(branchRef, lastKnown)
237
- call.respondDelta(RepositoryId (repository), newVersionHash, lastKnown)
246
+ call.respondDelta(RepositoryId (repository), newVersionHash, ObjectDeltaFilter ( lastKnown) )
238
247
}
239
248
240
249
override suspend fun RoutingContext.postRepositoryObjectsGetAll (repository : String ) {
@@ -282,7 +291,7 @@ class ModelReplicationServer(
282
291
if (repositoriesManager.getVersion(repositoryId(repository), versionHash) == null ) {
283
292
throw VersionNotFoundException (versionHash)
284
293
}
285
- call.respondDelta(RepositoryId (repository), versionHash, lastKnown)
294
+ call.respondDelta(RepositoryId (repository), versionHash, ObjectDeltaFilter ( lastKnown) )
286
295
}
287
296
288
297
override suspend fun RoutingContext.postRepositoryBranchQuery (
@@ -384,40 +393,40 @@ class ModelReplicationServer(
384
393
if (runRead { stores.getGlobalStoreClient()[versionHash] } == null ) {
385
394
throw VersionNotFoundException (versionHash)
386
395
}
387
- call.respondDelta(null , versionHash, lastKnown)
396
+ call.respondDelta(null , versionHash, ObjectDeltaFilter ( lastKnown) )
388
397
}
389
398
390
- private suspend fun ApplicationCall.respondDelta (repositoryId : RepositoryId ? , versionHash : String , baseVersionHash : String? ) {
399
+ private suspend fun ApplicationCall.respondDelta (repositoryId : RepositoryId ? , versionHash : String , filter : ObjectDeltaFilter ) {
391
400
val expectedTypes = request.acceptItems().map { ContentType .parse(it.value) }
392
401
return if (expectedTypes.any { it.match(VersionDeltaStreamV2 .CONTENT_TYPE ) }) {
393
- respondDeltaAsObjectStreamV2(repositoryId, versionHash, baseVersionHash )
402
+ respondDeltaAsObjectStreamV2(repositoryId, versionHash, filter )
394
403
} else if (expectedTypes.any { it.match(VersionDeltaStream .CONTENT_TYPE ) }) {
395
- respondDeltaAsObjectStreamV1(repositoryId, versionHash, baseVersionHash , false )
404
+ respondDeltaAsObjectStreamV1(repositoryId, versionHash, filter , false )
396
405
} else if (expectedTypes.any { it.match(ContentType .Application .Json ) }) {
397
- respondDeltaAsJson(repositoryId, versionHash, baseVersionHash )
406
+ respondDeltaAsJson(repositoryId, versionHash, filter )
398
407
} else {
399
- respondDeltaAsObjectStreamV1(repositoryId, versionHash, baseVersionHash , true )
408
+ respondDeltaAsObjectStreamV1(repositoryId, versionHash, filter , true )
400
409
}
401
410
}
402
411
403
- private suspend fun ApplicationCall.respondDeltaAsJson (repositoryId : RepositoryId ? , versionHash : String , baseVersionHash : String? ) {
412
+ private suspend fun ApplicationCall.respondDeltaAsJson (repositoryId : RepositoryId ? , versionHash : String , filter : ObjectDeltaFilter ) {
404
413
val delta = VersionDelta (
405
414
versionHash,
406
- baseVersionHash ,
407
- objectsMap = repositoriesManager.computeDelta(repositoryId, versionHash, baseVersionHash ).asMap(),
415
+ filter.knownVersions.firstOrNull() ,
416
+ objectsMap = repositoriesManager.computeDelta(repositoryId, versionHash, filter ).asMap(),
408
417
)
409
418
respond(delta)
410
419
}
411
420
412
421
private suspend fun ApplicationCall.respondDeltaAsObjectStreamV1 (
413
422
repositoryId : RepositoryId ? ,
414
423
versionHash : String ,
415
- baseVersionHash : String? ,
424
+ filter : ObjectDeltaFilter ,
416
425
plainText : Boolean ,
417
426
) {
418
427
// Call `computeDelta` before starting to respond.
419
428
// It could already throw an exception, and in that case we do not want a successful response status.
420
- val objectData = repositoriesManager.computeDelta(repositoryId, versionHash, baseVersionHash )
429
+ val objectData = repositoriesManager.computeDelta(repositoryId, versionHash, filter )
421
430
val contentType = if (plainText) ContentType .Text .Plain else VersionDeltaStream .CONTENT_TYPE
422
431
respondBytesWriter(contentType) {
423
432
this .useClosingWithoutCause {
@@ -434,8 +443,8 @@ class ModelReplicationServer(
434
443
}
435
444
}
436
445
437
- private suspend fun ApplicationCall.respondDeltaAsObjectStreamV2 (repositoryId : RepositoryId ? , versionHash : String , baseVersionHash : String? ) {
438
- val objectData = repositoriesManager.computeDelta(repositoryId, versionHash, baseVersionHash )
446
+ private suspend fun ApplicationCall.respondDeltaAsObjectStreamV2 (repositoryId : RepositoryId ? , versionHash : String , filter : ObjectDeltaFilter ) {
447
+ val objectData = repositoriesManager.computeDelta(repositoryId, versionHash, filter )
439
448
respondBytesWriter(VersionDeltaStreamV2 .CONTENT_TYPE ) {
440
449
this .useClosingWithoutCause {
441
450
VersionDeltaStreamV2 .encodeVersionDeltaStreamV2(this , versionHash, objectData.asStream())
0 commit comments