From c8e40ba9916b473ceb4e9448fd17b34c960afa37 Mon Sep 17 00:00:00 2001 From: Michael Huster Date: Mon, 8 Jan 2024 17:16:11 +0100 Subject: [PATCH 1/3] fix(model-server): fix node inspector not finding nodes in some cases --- .../model/server/handlers/ContentExplorer.kt | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/model-server/src/main/kotlin/org/modelix/model/server/handlers/ContentExplorer.kt b/model-server/src/main/kotlin/org/modelix/model/server/handlers/ContentExplorer.kt index 8c7edd3dd8..87acd946da 100644 --- a/model-server/src/main/kotlin/org/modelix/model/server/handlers/ContentExplorer.kt +++ b/model-server/src/main/kotlin/org/modelix/model/server/handlers/ContentExplorer.kt @@ -112,19 +112,24 @@ class ContentExplorer(private val client: IModelClient, private val repoManager: ) } get { - val id = call.parameters["nodeId"]!!.toLong() - var found: PNodeAdapter? = null - for (node in rootNodes) { - val candidate = PNodeAdapter(id, node.branch).takeIf { it.isValid } - if (candidate != null) { - found = candidate - break - } + val id = call.parameters["nodeId"]?.toLongOrNull() + ?: return@get call.respondText("node id not found", status = HttpStatusCode.NotFound) + + val versionHash = call.parameters["versionHash"] + ?: return@get call.respondText("version hash not found", status = HttpStatusCode.NotFound) + + val version = try { + CLVersion.loadFromHash(versionHash, client.storeCache) + } catch (ex: RuntimeException) { + return@get call.respondText("version not found", status = HttpStatusCode.NotFound) } - if (found == null) { - call.respondText("node id not found", status = HttpStatusCode.NotFound) + + val node = PNodeAdapter(id, TreePointer(version.getTree())).takeIf { it.isValid } + + if (node != null) { + call.respondHtml { body { nodeInspector(node) } } } else { - call.respondHtml { body { nodeInspector(found) } } + call.respondText("node id not found", status = HttpStatusCode.NotFound) } } } From a200727ea4e0cd80986ce5faf3e44be06c00c24b Mon Sep 17 00:00:00 2001 From: Michael Huster Date: Tue, 9 Jan 2024 17:05:27 +0100 Subject: [PATCH 2/3] test(model-server): add test for node inspector --- .../server/handlers/ContentExplorerTest.kt | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 model-server/src/test/kotlin/org/modelix/model/server/handlers/ContentExplorerTest.kt diff --git a/model-server/src/test/kotlin/org/modelix/model/server/handlers/ContentExplorerTest.kt b/model-server/src/test/kotlin/org/modelix/model/server/handlers/ContentExplorerTest.kt new file mode 100644 index 0000000000..73736cb617 --- /dev/null +++ b/model-server/src/test/kotlin/org/modelix/model/server/handlers/ContentExplorerTest.kt @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2024. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.modelix.model.server.handlers + +import io.ktor.client.call.body +import io.ktor.client.request.get +import io.ktor.client.request.post +import io.ktor.serialization.kotlinx.json.json +import io.ktor.server.plugins.contentnegotiation.ContentNegotiation +import io.ktor.server.resources.Resources +import io.ktor.server.routing.IgnoreTrailingSlash +import io.ktor.server.testing.ApplicationTestBuilder +import io.ktor.server.testing.testApplication +import io.ktor.server.websocket.WebSockets +import org.modelix.model.client.successful +import org.modelix.model.lazy.CLVersion +import org.modelix.model.server.api.v2.VersionDelta +import org.modelix.model.server.store.InMemoryStoreClient +import org.modelix.model.server.store.LocalModelClient +import kotlin.test.Test +import kotlin.test.assertTrue +import io.ktor.client.plugins.contentnegotiation.ContentNegotiation as ClientContentNegotiation + +class ContentExplorerTest { + + private val repoId = "test-repo" + private val modelClient = LocalModelClient(InMemoryStoreClient()) + private val repoManager = RepositoriesManager(modelClient) + + private fun runTest(body: suspend (ApplicationTestBuilder.() -> Unit)) { + testApplication { + install(WebSockets) + install(ContentNegotiation) { json() } + install(Resources) + install(IgnoreTrailingSlash) + application { + ModelReplicationServer(repoManager).init(this) + ContentExplorer(modelClient, repoManager).init(this) + } + + body() + } + } + + @Test + fun `node inspector finds root node`() = runTest { + val client = createClient { + install(ClientContentNegotiation) { json() } + } + + val delta: VersionDelta = client.post("/v2/repositories/$repoId/init").body() + + val versionHash = delta.versionHash + val version = CLVersion.loadFromHash(versionHash, modelClient.storeCache) + val nodeId = checkNotNull(version.getTree().root?.id) + + val response = client.get("/content/$versionHash/$nodeId/") + assertTrue(response.successful) + } +} From 39d18c140fdc969eb7918dbf0ea4d959c157c980 Mon Sep 17 00:00:00 2001 From: Michael Huster Date: Fri, 12 Jan 2024 15:17:13 +0100 Subject: [PATCH 3/3] chore(model-server): remove unused property --- .../model/server/handlers/ContentExplorer.kt | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/model-server/src/main/kotlin/org/modelix/model/server/handlers/ContentExplorer.kt b/model-server/src/main/kotlin/org/modelix/model/server/handlers/ContentExplorer.kt index 87acd946da..c7690bac59 100644 --- a/model-server/src/main/kotlin/org/modelix/model/server/handlers/ContentExplorer.kt +++ b/model-server/src/main/kotlin/org/modelix/model/server/handlers/ContentExplorer.kt @@ -37,7 +37,6 @@ import kotlinx.html.tr import kotlinx.html.ul import kotlinx.html.unsafe import org.modelix.api.html.Paths -import org.modelix.model.ModelFacade import org.modelix.model.api.BuiltinLanguages import org.modelix.model.api.INodeResolutionScope import org.modelix.model.api.ITree @@ -50,19 +49,6 @@ import kotlin.collections.set class ContentExplorer(private val client: IModelClient, private val repoManager: RepositoriesManager) { - private val rootNodes: List - get() { - val nodeList = mutableListOf() - - for (repoId in repoManager.getRepositories()) { - val branchRef = repoId.getBranchReference() - val version = ModelFacade.loadCurrentVersion(client, branchRef) ?: continue - val rootNode = PNodeAdapter(ITree.ROOT_ID, TreePointer(version.getTree())) - nodeList.add(rootNode) - } - return nodeList - } - fun init(application: Application) { application.routing { get {