Skip to content

Commit

Permalink
feat: add info controller
Browse files Browse the repository at this point in the history
  • Loading branch information
JonasKellerer committed Dec 12, 2023
1 parent 22e5f49 commit 78f9c69
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const val AMINO_ACID_INSERTIONS_ENDPOINT_DESCRIPTION =
"Returns a list of mutations along with the counts and proportions whose proportions are greater " +
"than or equal to the specified minProportion. Only sequences matching the specified " +
"sequence filters are considered."
const val INFO_ENDPOINT_DESCRIPTION = "Returns information about LAPIS"

const val ALIGNED_AMINO_ACID_SEQUENCE_ENDPOINT_DESCRIPTION =
"Returns a string of fasta formated aligned amino acid sequences. Only sequences matching the specified " +
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.genspectrum.lapis.controller

import io.swagger.v3.oas.annotations.Operation
import org.genspectrum.lapis.model.SiloQueryModel
import org.genspectrum.lapis.request.LapisInfo
import org.springframework.http.MediaType
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController

const val INFO_ROUTE = "/info"

@RestController
class InfoController(private val siloQueryModel: SiloQueryModel) {
@GetMapping(INFO_ROUTE, produces = [MediaType.APPLICATION_JSON_VALUE])
@Operation(description = INFO_ENDPOINT_DESCRIPTION)
fun getInfo(): LapisInfo {
val siloInfo = siloQueryModel.getInfo()
return LapisInfo(siloInfo.dataVersion)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import org.genspectrum.lapis.request.SequenceFiltersRequestWithFields
import org.genspectrum.lapis.response.AminoAcidInsertionResponse
import org.genspectrum.lapis.response.AminoAcidMutationResponse
import org.genspectrum.lapis.response.DetailsData
import org.genspectrum.lapis.response.InfoData
import org.genspectrum.lapis.response.NucleotideInsertionResponse
import org.genspectrum.lapis.response.NucleotideMutationResponse
import org.genspectrum.lapis.silo.SequenceType
Expand Down Expand Up @@ -156,4 +157,6 @@ class SiloQueryModel(
),
).joinToString("\n") { ">${it.sequenceKey}\n${it.sequence}" }
}

fun getInfo(): InfoData = siloClient.callInfo()
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import org.genspectrum.lapis.controller.OFFSET_PROPERTY
import org.genspectrum.lapis.controller.ORDER_BY_PROPERTY
import org.genspectrum.lapis.request.AminoAcidInsertion
import org.genspectrum.lapis.request.AminoAcidMutation
import org.genspectrum.lapis.request.LAPIS_DATA_VERSION_HEADER
import org.genspectrum.lapis.request.LapisInfo
import org.genspectrum.lapis.request.NucleotideInsertion
import org.genspectrum.lapis.request.NucleotideMutation
import org.genspectrum.lapis.request.OrderByField
Expand Down Expand Up @@ -255,16 +255,13 @@ private fun lapisResponseSchema(dataSchema: Schema<Any>) =
).required(listOf("data", "info"))

private fun infoResponseSchema() =
Schema<Any>().type("object")
.description("Information about LAPIS.")
Schema<LapisInfo>().type("object")
.description(LAPIS_INFO_DESCRIPTION)
.properties(
mapOf(
"dataVersion" to Schema<String>().type("string")
.description(
"$LAPIS_DATA_VERSION_DESCRIPTION " +
"Same as the value of the header \"$LAPIS_DATA_VERSION_HEADER\".",
)
.example("1702305399"),
.description(LAPIS_DATA_VERSION_RESPONSE_DESCRIPTION)
.example(LAPIS_DATA_VERSION_EXAMPLE),
),
).required(listOf("dataVersion"))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,13 @@ const val FORMAT_SCHEMA = "DataFormat"
const val FIELDS_TO_AGGREGATE_BY_SCHEMA = "FieldsToAggregateBy"
const val DETAILS_FIELDS_SCHEMA = "DetailsFields"

const val LAPIS_INFO_DESCRIPTION = "Information about LAPIS."
const val LAPIS_DATA_VERSION_EXAMPLE = "1702305399"
const val LAPIS_DATA_VERSION_DESCRIPTION = "The data version of data in SILO."
const val LAPIS_DATA_VERSION_HEADER_DESCRIPTION = "$LAPIS_DATA_VERSION_DESCRIPTION " +
"Same as the value returned in the info object in the response body."
const val LAPIS_DATA_VERSION_RESPONSE_DESCRIPTION = "$LAPIS_DATA_VERSION_DESCRIPTION " +
"Same as the value returned in the info object in the header '$LAPIS_DATA_VERSION_HEADER'."

@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
Expand All @@ -70,8 +76,7 @@ const val LAPIS_DATA_VERSION_DESCRIPTION = "The data version of data in SILO."
headers = [
Header(
name = LAPIS_DATA_VERSION_HEADER,
description = "$LAPIS_DATA_VERSION_DESCRIPTION " +
"Same as the value returned in the info object in the response body.",
description = LAPIS_DATA_VERSION_HEADER_DESCRIPTION,
schema = Schema(type = "string"),
),
],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package org.genspectrum.lapis.request

import io.swagger.v3.oas.annotations.media.Schema
import org.genspectrum.lapis.controller.LapisErrorResponse
import org.genspectrum.lapis.controller.LapisResponse
import org.genspectrum.lapis.openApi.LAPIS_DATA_VERSION_EXAMPLE
import org.genspectrum.lapis.openApi.LAPIS_DATA_VERSION_RESPONSE_DESCRIPTION
import org.genspectrum.lapis.openApi.LAPIS_INFO_DESCRIPTION
import org.genspectrum.lapis.silo.DataVersion
import org.springframework.core.MethodParameter
import org.springframework.http.MediaType
Expand All @@ -11,7 +15,13 @@ import org.springframework.http.server.ServerHttpResponse
import org.springframework.web.bind.annotation.ControllerAdvice
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice

data class LapisInfo(var dataVersion: String? = null)
@Schema(description = LAPIS_INFO_DESCRIPTION)
data class LapisInfo(
@Schema(
description = LAPIS_DATA_VERSION_RESPONSE_DESCRIPTION,
example = LAPIS_DATA_VERSION_EXAMPLE,
) var dataVersion: String? = null,
)

const val LAPIS_DATA_VERSION_HEADER = "Lapis-Data-Version"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ data class SequenceData(
val sequence: String,
)

data class InfoData(
val dataVersion: String,
)

@JsonComponent
class SequenceDataDeserializer(val databaseConfig: DatabaseConfig) : JsonDeserializer<SequenceData>() {
override fun deserialize(
Expand Down
42 changes: 33 additions & 9 deletions lapis2/src/main/kotlin/org/genspectrum/lapis/silo/SiloClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.genspectrum.lapis.silo
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import mu.KotlinLogging
import org.genspectrum.lapis.response.InfoData
import org.springframework.beans.factory.annotation.Value
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpStatus
Expand Down Expand Up @@ -35,6 +36,20 @@ class SiloClient(
.POST(HttpRequest.BodyPublishers.ofString(queryJson))
.build()

val response = send(client, request)

try {
return objectMapper.readValue(response.body(), query.action.typeReference).queryResult
} catch (exception: Exception) {
val message = "Could not parse response from silo: " + exception::class.toString() + " " + exception.message
throw RuntimeException(message, exception)
}
}

private fun send(
client: HttpClient,
request: HttpRequest?,
): HttpResponse<String> {
val response = try {
client.send(request, BodyHandlers.ofString())
} catch (exception: Exception) {
Expand Down Expand Up @@ -70,18 +85,27 @@ class SiloClient(
)
}

addDataVersion(response)
addDataVersionToRequestScope(response)
return response
}

try {
return objectMapper.readValue(response.body(), query.action.typeReference).queryResult
} catch (exception: Exception) {
val message = "Could not parse response from silo: " + exception::class.toString() + " " + exception.message
throw RuntimeException(message, exception)
}
fun callInfo(): InfoData {
log.info { "Calling SILO info" }

val client = HttpClient.newHttpClient()
val request = HttpRequest.newBuilder(URI("$siloUrl/info")).GET().build()

val response = send(client, request)

return InfoData(getDataVersion(response))
}

private fun addDataVersionToRequestScope(response: HttpResponse<String>) {
dataVersion.dataVersion = getDataVersion(response)
}

private fun addDataVersion(response: HttpResponse<String>) {
dataVersion.dataVersion = response.headers().firstValue("data-version").orElse("")
private fun getDataVersion(response: HttpResponse<String>): String {
return response.headers().firstValue("data-version").orElse("")
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.genspectrum.lapis.controller

import com.ninjasquad.springmockk.MockkBean
import io.mockk.every
import org.genspectrum.lapis.model.SiloQueryModel
import org.genspectrum.lapis.response.InfoData
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders
import org.springframework.test.web.servlet.result.MockMvcResultMatchers

@SpringBootTest
@AutoConfigureMockMvc
class InfoControllerTest(
@Autowired val mockMvc: MockMvc,
) {
@MockkBean
lateinit var siloQueryModelMock: SiloQueryModel

@Test
fun `GET info`() {
every {
siloQueryModelMock.getInfo()
} returns InfoData("1234")

mockMvc.perform(MockMvcRequestBuilders.get(INFO_ROUTE))
.andExpect(MockMvcResultMatchers.status().isOk)
.andExpect(MockMvcResultMatchers.jsonPath("\$.dataVersion").value("1234"))
}
}

0 comments on commit 78f9c69

Please sign in to comment.