works
This commit is contained in:
parent
000a984d04
commit
27e89c80fc
|
|
@ -6,9 +6,10 @@ import jakarta.validation.constraints.NotBlank
|
||||||
import jakarta.validation.constraints.NotNull
|
import jakarta.validation.constraints.NotNull
|
||||||
import jakarta.validation.constraints.Size
|
import jakarta.validation.constraints.Size
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
data class TelemetryRequest(
|
data class TelemetryRequest(
|
||||||
@field:NotNull val timestamp: Instant?,
|
@field:NotNull val timestamp: LocalDateTime?,
|
||||||
@field:NotNull val platform: TelemetryPlatform?,
|
@field:NotNull val platform: TelemetryPlatform?,
|
||||||
@field:NotBlank val appVersion: String,
|
@field:NotBlank val appVersion: String,
|
||||||
@field:Size(max = 200) val note: String? = null
|
@field:Size(max = 200) val note: String? = null
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package com.mosenioring.app.telemetry
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
import java.time.ZoneOffset
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
class TelemetryService {
|
class TelemetryService {
|
||||||
|
|
@ -10,6 +11,7 @@ class TelemetryService {
|
||||||
|
|
||||||
fun recordTestTelemetry(request: TelemetryRequest, user: AuthenticatedUser): TelemetryResponse {
|
fun recordTestTelemetry(request: TelemetryRequest, user: AuthenticatedUser): TelemetryResponse {
|
||||||
val timestamp = requireNotNull(request.timestamp) { "Missing timestamp" }
|
val timestamp = requireNotNull(request.timestamp) { "Missing timestamp" }
|
||||||
|
.toInstant(ZoneOffset.UTC)
|
||||||
val platform = requireNotNull(request.platform) { "Missing platform" }
|
val platform = requireNotNull(request.platform) { "Missing platform" }
|
||||||
val echo = TelemetryEcho(
|
val echo = TelemetryEcho(
|
||||||
timestamp = timestamp,
|
timestamp = timestamp,
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ class TelemetryControllerTest {
|
||||||
|
|
||||||
val requestBody = """
|
val requestBody = """
|
||||||
{
|
{
|
||||||
"timestamp": "2024-01-01T00:00:00Z",
|
"timestamp": "2024-01-01T00:00:00",
|
||||||
"platform": "android",
|
"platform": "android",
|
||||||
"appVersion": "dev",
|
"appVersion": "dev",
|
||||||
"note": "test call from mobile"
|
"note": "test call from mobile"
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
import org.junit.jupiter.api.Assertions.assertTrue
|
import org.junit.jupiter.api.Assertions.assertTrue
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
class TelemetryServiceTest {
|
class TelemetryServiceTest {
|
||||||
|
|
||||||
|
|
@ -11,7 +12,7 @@ class TelemetryServiceTest {
|
||||||
fun `records telemetry and returns response`() {
|
fun `records telemetry and returns response`() {
|
||||||
val service = TelemetryService()
|
val service = TelemetryService()
|
||||||
val request = TelemetryRequest(
|
val request = TelemetryRequest(
|
||||||
timestamp = Instant.parse("2024-01-02T12:00:00Z"),
|
timestamp = LocalDateTime.parse("2024-01-02T12:00:00"),
|
||||||
platform = TelemetryPlatform.IOS,
|
platform = TelemetryPlatform.IOS,
|
||||||
appVersion = "dev",
|
appVersion = "dev",
|
||||||
note = "test call from mobile"
|
note = "test call from mobile"
|
||||||
|
|
@ -28,7 +29,7 @@ class TelemetryServiceTest {
|
||||||
|
|
||||||
assertEquals("ok", response.status)
|
assertEquals("ok", response.status)
|
||||||
assertEquals("user-42", response.userId)
|
assertEquals("user-42", response.userId)
|
||||||
assertEquals(request.timestamp, response.echo.timestamp)
|
assertEquals(request.timestamp?.toInstant(java.time.ZoneOffset.UTC), response.echo.timestamp)
|
||||||
assertEquals(request.platform, response.echo.platform)
|
assertEquals(request.platform, response.echo.platform)
|
||||||
assertEquals(request.appVersion, response.echo.appVersion)
|
assertEquals(request.appVersion, response.echo.appVersion)
|
||||||
assertEquals(request.note, response.echo.note)
|
assertEquals(request.note, response.echo.note)
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import org.springframework.http.HttpStatus
|
||||||
import org.springframework.http.ProblemDetail
|
import org.springframework.http.ProblemDetail
|
||||||
import org.springframework.validation.FieldError
|
import org.springframework.validation.FieldError
|
||||||
import org.springframework.web.ErrorResponseException
|
import org.springframework.web.ErrorResponseException
|
||||||
|
import org.springframework.http.converter.HttpMessageNotReadableException
|
||||||
import org.springframework.web.bind.MethodArgumentNotValidException
|
import org.springframework.web.bind.MethodArgumentNotValidException
|
||||||
import org.springframework.web.bind.annotation.ExceptionHandler
|
import org.springframework.web.bind.annotation.ExceptionHandler
|
||||||
import org.springframework.web.bind.annotation.RestControllerAdvice
|
import org.springframework.web.bind.annotation.RestControllerAdvice
|
||||||
|
|
@ -42,6 +43,17 @@ class ProblemDetailsAdvice {
|
||||||
return detail
|
return detail
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(HttpMessageNotReadableException::class)
|
||||||
|
fun handleNotReadable(ex: HttpMessageNotReadableException, request: HttpServletRequest): ProblemDetail {
|
||||||
|
val detail = ProblemDetail.forStatus(HttpStatus.BAD_REQUEST)
|
||||||
|
detail.title = "Malformed request"
|
||||||
|
detail.detail = ex.mostSpecificCause.message ?: ex.message
|
||||||
|
detail.type = java.net.URI.create("https://httpstatuses.io/400")
|
||||||
|
detail.setProperty("code", "INVALID_JSON")
|
||||||
|
detail.setProperty("path", request.requestURI)
|
||||||
|
return detail
|
||||||
|
}
|
||||||
|
|
||||||
@ExceptionHandler(IllegalStateException::class)
|
@ExceptionHandler(IllegalStateException::class)
|
||||||
fun handleIllegalState(ex: IllegalStateException, request: HttpServletRequest): ProblemDetail {
|
fun handleIllegalState(ex: IllegalStateException, request: HttpServletRequest): ProblemDetail {
|
||||||
val detail = ProblemDetail.forStatus(HttpStatus.CONFLICT)
|
val detail = ProblemDetail.forStatus(HttpStatus.CONFLICT)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue