Skip to content

Commit 6442665

Browse files
author
Oleksandr Dzhychko
authored
Merge pull request #632 from modelix/MODELIX-843
perf(model-client): consistently process version streams while receiving data
2 parents c9d8f6f + ff06d3a commit 6442665

File tree

2 files changed

+54
-35
lines changed

2 files changed

+54
-35
lines changed

model-client/src/commonMain/kotlin/org/modelix/model/client2/ModelClientV2.kt

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import io.ktor.client.request.HttpRequestBuilder
2525
import io.ktor.client.request.get
2626
import io.ktor.client.request.post
2727
import io.ktor.client.request.prepareGet
28+
import io.ktor.client.request.preparePost
2829
import io.ktor.client.request.put
2930
import io.ktor.client.request.setBody
3031
import io.ktor.client.statement.HttpResponse
@@ -123,14 +124,15 @@ class ModelClientV2(
123124
override fun getUserId(): String? = clientProvidedUserId ?: serverProvidedUserId
124125

125126
override suspend fun initRepository(repository: RepositoryId): IVersion {
126-
val response = httpClient.post {
127+
return httpClient.preparePost {
127128
url {
128129
takeFrom(baseUrl)
129130
appendPathSegmentsEncodingSlash("repositories", repository.id, "init")
130131
}
131132
useVersionStreamFormat()
133+
}.execute { response ->
134+
createVersion(null, response.readVersionDelta())
132135
}
133-
return createVersion(null, response.readVersionDelta())
134136
}
135137

136138
override suspend fun listRepositories(): List<RepositoryId> {
@@ -168,7 +170,7 @@ class ModelClientV2(
168170
@Deprecated("repository ID is required for permission checks")
169171
@DeprecationInfo("3.7.0", "May be removed with the next major release. Also remove the endpoint from the model-server.")
170172
override suspend fun loadVersion(versionHash: String, baseVersion: IVersion?): IVersion {
171-
val response = httpClient.post {
173+
return httpClient.prepareGet {
172174
url {
173175
takeFrom(baseUrl)
174176
appendPathSegments("versions", versionHash)
@@ -177,16 +179,17 @@ class ModelClientV2(
177179
}
178180
}
179181
useVersionStreamFormat()
182+
}.execute { response ->
183+
createVersion(baseVersion as CLVersion?, response.readVersionDelta())
180184
}
181-
return createVersion(baseVersion as CLVersion?, response.readVersionDelta())
182185
}
183186

184187
override suspend fun loadVersion(
185188
repositoryId: RepositoryId,
186189
versionHash: String,
187190
baseVersion: IVersion?,
188191
): IVersion {
189-
val response = httpClient.post {
192+
return httpClient.prepareGet {
190193
url {
191194
takeFrom(baseUrl)
192195
appendPathSegments("repositories", repositoryId.id, "versions", versionHash)
@@ -195,8 +198,9 @@ class ModelClientV2(
195198
}
196199
}
197200
useVersionStreamFormat()
201+
}.execute { response ->
202+
createVersion(baseVersion as CLVersion?, response.readVersionDelta())
198203
}
199-
return createVersion(baseVersion as CLVersion?, response.readVersionDelta())
200204
}
201205

202206
override suspend fun push(branch: BranchReference, version: IVersion, baseVersion: IVersion?): IVersion {
@@ -213,16 +217,17 @@ class ModelClientV2(
213217
} else {
214218
VersionDelta(version.getContentHash(), null, objectsMap = objects)
215219
}
216-
val response = httpClient.post {
220+
return httpClient.preparePost {
217221
url {
218222
takeFrom(baseUrl)
219223
appendPathSegmentsEncodingSlash("repositories", branch.repositoryId.id, "branches", branch.branchName)
220224
}
221225
useVersionStreamFormat()
222226
contentType(ContentType.Application.Json)
223227
setBody(delta)
228+
}.execute { response ->
229+
createVersion(version, response.readVersionDelta())
224230
}
225-
return createVersion(version, response.readVersionDelta())
226231
}
227232

228233
private suspend fun uploadObjects(repository: RepositoryId, objects: Sequence<Pair<String, String>>) {

model-server/src/test/kotlin/org/modelix/model/server/ModelClientV2Test.kt

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,15 @@ class ModelClientV2Test {
6161
block()
6262
}
6363

64+
private suspend fun ApplicationTestBuilder.createModelClient(): ModelClientV2 {
65+
val url = "http://localhost/v2"
66+
val modelClient = ModelClientV2.builder().url(url).client(client).build().also { it.init() }
67+
return modelClient
68+
}
69+
6470
@Test
6571
fun test_t1() = runTest {
66-
val url = "http://localhost/v2"
67-
val client = ModelClientV2.builder().url(url).client(client).build().also { it.init() }
72+
val client = createModelClient()
6873

6974
val repositoryId = RepositoryId("repo1")
7075
val initialVersion = client.initRepository(repositoryId)
@@ -101,9 +106,7 @@ class ModelClientV2Test {
101106

102107
@Test
103108
fun modelqlSmokeTest() = runTest {
104-
val url = "http://localhost/v2"
105-
val client = ModelClientV2.builder().url(url).client(client).build().also { it.init() }
106-
109+
val client = createModelClient()
107110
val repositoryId = RepositoryId("repo1")
108111
val branchRef = repositoryId.getBranchReference()
109112
val initialVersion = client.initRepository(repositoryId)
@@ -116,9 +119,7 @@ class ModelClientV2Test {
116119

117120
@Test
118121
fun testSlashesInPathSegmentsFromRepositoryIdAndBranchId() = runTest {
119-
val url = "http://localhost/v2"
120-
val client = ModelClientV2.builder().url(url).client(client).build()
121-
client.init()
122+
val client = createModelClient()
122123
val repositoryId = RepositoryId("repo/v1")
123124
val initialVersion = client.initRepository(repositoryId)
124125
val branchId = repositoryId.getBranchReference("my-branch/v1")
@@ -131,14 +132,7 @@ class ModelClientV2Test {
131132

132133
@Test
133134
fun `user id can be provided to client after creation`() = runTest {
134-
val url = "http://localhost/v2"
135-
val modelClient = ModelClientV2
136-
.builder()
137-
.url(url)
138-
.client(client)
139-
.build()
140-
.also { it.init() }
141-
135+
val modelClient = createModelClient()
142136
val userId = "a_user_id"
143137
modelClient.setClientProvideUserId(userId)
144138

@@ -148,23 +142,24 @@ class ModelClientV2Test {
148142
@Test
149143
fun `user id provided by client can be removed`() = runTest {
150144
val url = "http://localhost/v2"
145+
val userId = "a_user_id"
151146
val modelClient = ModelClientV2
152147
.builder()
153148
.url(url)
154149
.client(client)
155-
.userId("a_user_id")
150+
.userId(userId)
156151
.build()
157-
.also { it.init() }
152+
modelClient.init()
158153

154+
assertEquals(userId, modelClient.getUserId())
159155
modelClient.setClientProvideUserId(null)
160156

161157
assertEquals("localhost", modelClient.getUserId())
162158
}
163159

164160
@Test
165161
fun `newly created repository can be removed`() = runTest {
166-
val url = "http://localhost/v2"
167-
val client = ModelClientV2.builder().url(url).client(client).build().also { it.init() }
162+
val client = createModelClient()
168163
val repositoryId = RepositoryId(UUID.randomUUID().toString())
169164
client.initRepository(repositoryId)
170165

@@ -177,8 +172,7 @@ class ModelClientV2Test {
177172

178173
@Test
179174
fun `non-existing repository cannot be removed`() = runTest {
180-
val url = "http://localhost/v2"
181-
val client = ModelClientV2.builder().url(url).client(client).build().also { it.init() }
175+
val client = createModelClient()
182176
val repositoryId = RepositoryId(UUID.randomUUID().toString())
183177

184178
val success = client.deleteRepository(repositoryId)
@@ -191,9 +185,8 @@ class ModelClientV2Test {
191185
@Test
192186
fun `pulling existing versions pulls all referenced objects`() = runTest {
193187
// Arrange
194-
val url = "http://localhost/v2"
195-
val modelClientForArrange = ModelClientV2.builder().url(url).client(client).build().also { it.init() }
196-
val modelClientForAssert = ModelClientV2.builder().url(url).client(client).build().also { it.init() }
188+
val modelClientForArrange = createModelClient()
189+
val modelClientForAssert = createModelClient()
197190
val repositoryId = RepositoryId("repo1")
198191
val branchId = repositoryId.getBranchReference("my-branch")
199192
modelClientForArrange.runWrite(branchId) { root ->
@@ -221,8 +214,7 @@ class ModelClientV2Test {
221214
@Test
222215
fun `writing no data does not create empty versions`() = runTest {
223216
// Arrange
224-
val url = "http://localhost/v2"
225-
val modelClient = ModelClientV2.builder().url(url).client(client).build().also { it.init() }
217+
val modelClient = createModelClient()
226218
val repositoryId = RepositoryId("repo1")
227219
val branchId = repositoryId.getBranchReference("master")
228220
modelClient.initRepository(repositoryId)
@@ -237,4 +229,26 @@ class ModelClientV2Test {
237229
val versionAfterRunWrite = modelClient.pullIfExists(branchId)!!
238230
assertEquals(versionAfterBeforeWrite.getContentHash(), versionAfterRunWrite.getContentHash())
239231
}
232+
233+
@Test
234+
fun `client can load version`() = runTest {
235+
val modelClient = createModelClient()
236+
val repositoryId = RepositoryId("aRepo")
237+
val initialVersion = modelClient.initRepository(repositoryId)
238+
239+
val loadedVersion = modelClient.loadVersion(repositoryId, initialVersion.getContentHash(), initialVersion)
240+
241+
assertEquals(initialVersion.getContentHash(), loadedVersion.getContentHash())
242+
}
243+
244+
@Test
245+
fun `client can load version (deprecated endpoint without repository)`() = runTest {
246+
val modelClient = createModelClient()
247+
val repositoryId = RepositoryId("aRepo")
248+
val initialVersion = modelClient.initRepository(repositoryId)
249+
250+
val loadedVersion = modelClient.loadVersion(initialVersion.getContentHash(), initialVersion)
251+
252+
assertEquals(initialVersion.getContentHash(), loadedVersion.getContentHash())
253+
}
240254
}

0 commit comments

Comments
 (0)