Skip to content

Commit

Permalink
feat: add info to lapis response
Browse files Browse the repository at this point in the history
  • Loading branch information
JonasKellerer committed Dec 12, 2023
1 parent d939f44 commit afff4ae
Show file tree
Hide file tree
Showing 13 changed files with 107 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package org.genspectrum.lapis.controller

import org.genspectrum.lapis.request.LapisInfo
import org.springframework.http.ProblemDetail

data class LapisResponse<Data>(val data: Data)
data class LapisResponse<Data>(val data: Data, val info: LapisInfo = LapisInfo())

data class LapisErrorResponse(val error: ProblemDetail)
data class LapisErrorResponse(val error: ProblemDetail, val info: LapisInfo = LapisInfo())
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +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.NucleotideInsertion
import org.genspectrum.lapis.request.NucleotideMutation
import org.genspectrum.lapis.request.OrderByField
Expand Down Expand Up @@ -249,8 +250,23 @@ private fun lapisResponseSchema(dataSchema: Schema<Any>) =
Schema<Any>().type("object").properties(
mapOf(
"data" to Schema<Any>().type("array").items(dataSchema),
"info" to infoResponseSchema(),
),
).required(listOf("data"))
).required(listOf("data", "info"))

private fun infoResponseSchema() =
Schema<Any>().type("object")
.description("Information about LAPIS.")
.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"),
),
).required(listOf("dataVersion"))

private fun metadataFieldSchemas(databaseConfig: DatabaseConfig) =
databaseConfig.schema.metadata.associate { it.name to Schema<String>().type(mapToOpenApiType(it.type)) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ const val FORMAT_SCHEMA = "DataFormat"
const val FIELDS_TO_AGGREGATE_BY_SCHEMA = "FieldsToAggregateBy"
const val DETAILS_FIELDS_SCHEMA = "DetailsFields"

const val LAPIS_DATA_VERSION_DESCRIPTION = "The data version of data in SILO."

@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
@Operation
Expand All @@ -68,7 +70,8 @@ const val DETAILS_FIELDS_SCHEMA = "DetailsFields"
headers = [
Header(
name = LAPIS_DATA_VERSION_HEADER,
description = "A timestamp of when the data was last updated.",
description = "$LAPIS_DATA_VERSION_DESCRIPTION " +
"Same as the value returned in the info object in the response body.",
schema = Schema(type = "string"),
),
],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
package org.genspectrum.lapis.request

import org.genspectrum.lapis.controller.LapisErrorResponse
import org.genspectrum.lapis.controller.LapisResponse
import org.genspectrum.lapis.silo.DataVersion
import org.springframework.core.MethodParameter
import org.springframework.http.MediaType
import org.springframework.http.converter.HttpMessageConverter
import org.springframework.http.server.ServerHttpRequest
import org.springframework.http.server.ServerHttpResponse
import org.springframework.stereotype.Component
import org.springframework.web.bind.annotation.ControllerAdvice
import org.springframework.web.context.annotation.RequestScope
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice

@Component
@RequestScope
class DataVersion {
var dataVersion: String? = null
}
data class LapisInfo(var dataVersion: String? = null)

const val LAPIS_DATA_VERSION_HEADER = "Lapis-Data-Version"

Expand All @@ -29,6 +26,12 @@ class ResponseBodyAdviceDataVersion(private val dataVersion: DataVersion) : Resp
response: ServerHttpResponse,
): Any? {
response.headers.add(LAPIS_DATA_VERSION_HEADER, dataVersion.dataVersion)

when (body) {
is LapisResponse<*> -> return LapisResponse(body.data, LapisInfo(dataVersion.dataVersion))
is LapisErrorResponse -> return LapisErrorResponse(body.error, LapisInfo(dataVersion.dataVersion))
}

return body
}

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

import org.springframework.stereotype.Component
import org.springframework.web.context.annotation.RequestScope

@Component
@RequestScope
data class DataVersion(var dataVersion: String? = null)
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ 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.request.DataVersion
import org.springframework.beans.factory.annotation.Value
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpStatus
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import io.mockk.every
import io.mockk.verify
import org.genspectrum.lapis.controller.AGGREGATED_ROUTE
import org.genspectrum.lapis.model.SiloQueryModel
import org.genspectrum.lapis.request.LapisInfo
import org.genspectrum.lapis.request.SequenceFiltersRequestWithFields
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
Expand Down Expand Up @@ -38,10 +39,17 @@ class ProtectedDataAuthorizationTest(

private val validRoute = AGGREGATED_ROUTE

@MockkBean
lateinit var lapisInfo: LapisInfo

@BeforeEach
fun setUp() {
every { siloQueryModelMock.getAggregated(any()) } returns emptyList()

every {
lapisInfo.dataVersion
} returns "1234"

MockKAnnotations.init(this)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import io.mockk.MockKAnnotations
import io.mockk.MockKMatcherScope
import io.mockk.every
import org.genspectrum.lapis.model.SiloNotImplementedError
import org.genspectrum.lapis.request.LapisInfo
import org.genspectrum.lapis.response.AggregationData
import org.genspectrum.lapis.silo.DataVersion
import org.genspectrum.lapis.silo.SiloException
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
Expand All @@ -26,17 +28,24 @@ class ExceptionHandlerTest(
@MockkBean
lateinit var lapisController: LapisController

@MockkBean
lateinit var dataVersion: DataVersion

@BeforeEach
fun setUp() {
MockKAnnotations.init(this)

every {
dataVersion.dataVersion
} returns "1234"
}

private val validRoute = "/aggregated"

private fun MockKMatcherScope.validControllerCall() =
lapisController.aggregated(any(), any(), any(), any(), any(), any(), any())

private val validResponse = LapisResponse(emptyList<AggregationData>())
private val validResponse = LapisResponse(emptyList<AggregationData>(), LapisInfo())

@Test
fun `throw NOT_FOUND(404) when route is not found`() {
Expand All @@ -60,6 +69,9 @@ class ExceptionHandlerTest(
"error": {
"title": "Internal Server Error",
"detail": "SomeMessage"
},
"info": {
"dataVersion": "1234"
}
}
""",
Expand All @@ -81,6 +93,9 @@ class ExceptionHandlerTest(
"error": {
"title": "SomeTitle",
"detail": "SomeMessage"
},
"info": {
"dataVersion": "1234"
}
}
""",
Expand All @@ -102,6 +117,9 @@ class ExceptionHandlerTest(
"error": {
"title": "Bad Request",
"detail": "SomeMessage"
},
"info": {
"dataVersion": "1234"
}
}
""",
Expand All @@ -123,6 +141,9 @@ class ExceptionHandlerTest(
"error": {
"title": "Not Implemented",
"detail": "SomeMessage"
},
"info": {
"dataVersion": "1234"
}
}
""",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import com.ninjasquad.springmockk.MockkBean
import io.mockk.every
import org.genspectrum.lapis.model.SiloQueryModel
import org.genspectrum.lapis.request.AminoAcidInsertion
import org.genspectrum.lapis.request.LapisInfo
import org.genspectrum.lapis.request.NucleotideInsertion
import org.genspectrum.lapis.request.Order
import org.genspectrum.lapis.request.OrderByField
import org.genspectrum.lapis.request.SequenceFiltersRequestWithFields
import org.genspectrum.lapis.response.AggregationData
import org.hamcrest.Matchers
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.Arguments
Expand All @@ -33,6 +35,16 @@ class LapisControllerCommonFieldsTest(
@MockkBean
lateinit var siloQueryModelMock: SiloQueryModel

@MockkBean
lateinit var lapisInfo: LapisInfo

@BeforeEach
fun setup() {
every {
lapisInfo.dataVersion
} returns "1234"
}

@Test
fun `GET aggregated with a single orderBy field`() {
every {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import com.fasterxml.jackson.databind.node.TextNode
import com.ninjasquad.springmockk.MockkBean
import io.mockk.every
import org.genspectrum.lapis.model.SiloQueryModel
import org.genspectrum.lapis.request.LapisInfo
import org.genspectrum.lapis.request.SequenceFiltersRequestWithFields
import org.genspectrum.lapis.response.AggregationData
import org.genspectrum.lapis.response.AminoAcidInsertionResponse
import org.genspectrum.lapis.response.AminoAcidMutationResponse
import org.genspectrum.lapis.response.DetailsData
import org.genspectrum.lapis.response.NucleotideInsertionResponse
import org.genspectrum.lapis.response.NucleotideMutationResponse
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.Arguments
import org.junit.jupiter.params.provider.MethodSource
Expand All @@ -37,6 +39,16 @@ class LapisControllerCsvTest(
@MockkBean
lateinit var siloQueryModelMock: SiloQueryModel

@MockkBean
lateinit var lapisInfo: LapisInfo

@BeforeEach
fun setup() {
every {
lapisInfo.dataVersion
} returns "1234"
}

@ParameterizedTest(name = "GET {0} returns empty JSON")
@MethodSource("getEndpoints")
fun `GET returns empty json`(endpoint: String) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import com.fasterxml.jackson.databind.node.TextNode
import com.ninjasquad.springmockk.MockkBean
import io.mockk.every
import org.genspectrum.lapis.model.SiloQueryModel
import org.genspectrum.lapis.request.DataVersion
import org.genspectrum.lapis.request.MutationProportionsRequest
import org.genspectrum.lapis.request.NucleotideMutation
import org.genspectrum.lapis.request.SequenceFiltersRequest
Expand All @@ -16,6 +15,7 @@ import org.genspectrum.lapis.response.AminoAcidMutationResponse
import org.genspectrum.lapis.response.DetailsData
import org.genspectrum.lapis.response.NucleotideInsertionResponse
import org.genspectrum.lapis.response.NucleotideMutationResponse
import org.genspectrum.lapis.silo.DataVersion
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.params.ParameterizedTest
Expand Down Expand Up @@ -67,6 +67,7 @@ class LapisControllerTest(
.andExpect(jsonPath("\$.data[0].country").value("Switzerland"))
.andExpect(jsonPath("\$.data[0].age").value(42))
.andExpect(header().stringValues("Lapis-Data-Version", "1234"))
.andExpect(jsonPath("\$.info.dataVersion").value(1234))
}

@Test
Expand All @@ -87,6 +88,7 @@ class LapisControllerTest(
.andExpect(status().isOk)
.andExpect(jsonPath("\$.data[0].count").value(0))
.andExpect(header().stringValues("Lapis-Data-Version", "1234"))
.andExpect(jsonPath("\$.info.dataVersion").value(1234))
}

@Test
Expand Down Expand Up @@ -170,6 +172,7 @@ class LapisControllerTest(
.andExpect(jsonPath("\$.data[0].proportion").value(0.5))
.andExpect(jsonPath("\$.data[0].count").value(42))
.andExpect(header().stringValues("Lapis-Data-Version", "1234"))
.andExpect(jsonPath("\$.info.dataVersion").value(1234))
}

@ParameterizedTest(name = "GET {0} with minProportion")
Expand Down Expand Up @@ -215,6 +218,7 @@ class LapisControllerTest(
.andExpect(jsonPath("\$.data[0].proportion").value(0.5))
.andExpect(jsonPath("\$.data[0].count").value(42))
.andExpect(header().stringValues("Lapis-Data-Version", "1234"))
.andExpect(jsonPath("\$.info.dataVersion").value(1234))
}

@ParameterizedTest(name = "POST {0} with invalid minProportion returns bad request")
Expand Down Expand Up @@ -272,6 +276,7 @@ class LapisControllerTest(
.andExpect(jsonPath("\$.data[0].insertion").value("the insertion"))
.andExpect(jsonPath("\$.data[0].count").value(42))
.andExpect(header().stringValues("Lapis-Data-Version", "1234"))
.andExpect(jsonPath("\$.info.dataVersion").value(1234))
}

@ParameterizedTest(name = "GET {0}")
Expand All @@ -286,6 +291,7 @@ class LapisControllerTest(
.andExpect(jsonPath("\$.data[0].insertion").value("the insertion"))
.andExpect(jsonPath("\$.data[0].count").value(42))
.andExpect(header().stringValues("Lapis-Data-Version", "1234"))
.andExpect(jsonPath("\$.info.dataVersion").value(1234))
}

private fun setupInsertionMock(endpoint: String) {
Expand Down Expand Up @@ -335,6 +341,7 @@ class LapisControllerTest(
.andExpect(jsonPath("\$.data[0].country").value("Switzerland"))
.andExpect(jsonPath("\$.data[0].age").value(42))
.andExpect(header().stringValues("Lapis-Data-Version", "1234"))
.andExpect(jsonPath("\$.info.dataVersion").value(1234))
}

@Test
Expand Down Expand Up @@ -369,6 +376,7 @@ class LapisControllerTest(
.andExpect(jsonPath("\$.data[0].country").value("Switzerland"))
.andExpect(jsonPath("\$.data[0].age").value(42))
.andExpect(header().stringValues("Lapis-Data-Version", "1234"))
.andExpect(jsonPath("\$.info.dataVersion").value(1234))
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import io.mockk.every
import org.genspectrum.lapis.config.REFERENCE_GENOME_GENES_APPLICATION_ARG_PREFIX
import org.genspectrum.lapis.config.REFERENCE_GENOME_SEGMENTS_APPLICATION_ARG_PREFIX
import org.genspectrum.lapis.model.SiloQueryModel
import org.genspectrum.lapis.request.DataVersion
import org.genspectrum.lapis.request.SequenceFiltersRequest
import org.genspectrum.lapis.silo.DataVersion
import org.genspectrum.lapis.silo.SequenceType
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import io.mockk.every
import org.genspectrum.lapis.config.REFERENCE_GENOME_GENES_APPLICATION_ARG_PREFIX
import org.genspectrum.lapis.config.REFERENCE_GENOME_SEGMENTS_APPLICATION_ARG_PREFIX
import org.genspectrum.lapis.model.SiloQueryModel
import org.genspectrum.lapis.request.DataVersion
import org.genspectrum.lapis.request.SequenceFiltersRequest
import org.genspectrum.lapis.silo.DataVersion
import org.genspectrum.lapis.silo.SequenceType
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
Expand Down

0 comments on commit afff4ae

Please sign in to comment.