From 461f917505aee88aca46e182aebc2e85e96c473d Mon Sep 17 00:00:00 2001 From: Pavel Salamon Date: Wed, 22 May 2024 10:04:40 +0200 Subject: [PATCH 01/25] response envelope --- .../api/controller/BaseController.scala | 15 ++++++- .../api/controller/CheckpointController.scala | 5 ++- .../controller/CheckpointControllerImpl.scala | 18 +++++--- .../controller/PartitioningController.scala | 12 +++-- .../PartitioningControllerImpl.scala | 44 +++++++++++-------- .../atum/server/api/http/BaseEndpoints.scala | 2 +- .../absa/atum/server/api/http/Endpoints.scala | 20 +++++---- .../atum/server/api/http/ServerOptions.scala | 2 +- .../atum/server/model/ErrorResponse.scala | 34 +++++++------- .../atum/server/model/PlayJsonImplicits.scala | 4 ++ .../atum/server/model/SuccessResponse.scala | 26 +++++++++++ .../controller/CheckpointControllerSpec.scala | 12 +++-- .../PartitioningControllerSpec.scala | 41 +++++++++-------- .../http/CreateCheckpointEndpointSpec.scala | 11 ++--- .../http/CreatePartitioningEndpointSpec.scala | 9 ++-- 15 files changed, 159 insertions(+), 96 deletions(-) create mode 100644 server/src/main/scala/za/co/absa/atum/server/model/SuccessResponse.scala diff --git a/server/src/main/scala/za/co/absa/atum/server/api/controller/BaseController.scala b/server/src/main/scala/za/co/absa/atum/server/api/controller/BaseController.scala index 16414def2..9a3fa7df8 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/controller/BaseController.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/controller/BaseController.scala @@ -17,7 +17,8 @@ package za.co.absa.atum.server.api.controller import za.co.absa.atum.server.api.exception.ServiceError -import za.co.absa.atum.server.model.{ErrorResponse, GeneralErrorResponse, InternalServerErrorResponse} +import za.co.absa.atum.server.model.ErrorResponse.{ErrorResponse, GeneralErrorResponse, InternalServerErrorResponse} +import za.co.absa.atum.server.model.SuccessResponse.{MultiSuccessResponse, SingleSuccessResponse} import za.co.absa.fadb.exceptions.StatusException import zio._ @@ -40,4 +41,16 @@ trait BaseController { } } + + protected def mapToSingleSingleSuccessResponse[A]( + effect: IO[ErrorResponse, A] + ): IO[ErrorResponse, SingleSuccessResponse[A]] = { + effect.map(SingleSuccessResponse(_)) + } + + protected def mapToSingleMultiSuccessResponse[A]( + effect: IO[ErrorResponse, Seq[A]] + ): IO[ErrorResponse, MultiSuccessResponse[A]] = { + effect.map(MultiSuccessResponse(_)) + } } diff --git a/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointController.scala b/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointController.scala index 082e18b52..082d6b3b0 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointController.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointController.scala @@ -17,11 +17,12 @@ package za.co.absa.atum.server.api.controller import za.co.absa.atum.model.dto.CheckpointDTO -import za.co.absa.atum.server.model.ErrorResponse +import za.co.absa.atum.server.model.ErrorResponse.ErrorResponse +import za.co.absa.atum.server.model.SuccessResponse.SingleSuccessResponse import zio.IO import zio.macros.accessible @accessible trait CheckpointController { - def createCheckpoint(checkpointDTO: CheckpointDTO): IO[ErrorResponse, CheckpointDTO] + def createCheckpoint(checkpointDTO: CheckpointDTO): IO[ErrorResponse, SingleSuccessResponse[CheckpointDTO]] } diff --git a/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointControllerImpl.scala b/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointControllerImpl.scala index f1e3330c0..d7757d034 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointControllerImpl.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointControllerImpl.scala @@ -18,16 +18,20 @@ package za.co.absa.atum.server.api.controller import za.co.absa.atum.model.dto.CheckpointDTO import za.co.absa.atum.server.api.service.CheckpointService -import za.co.absa.atum.server.model.ErrorResponse +import za.co.absa.atum.server.model.ErrorResponse.ErrorResponse +import za.co.absa.atum.server.model.SuccessResponse.SingleSuccessResponse import zio._ -class CheckpointControllerImpl(checkpointService: CheckpointService) - extends CheckpointController with BaseController { +class CheckpointControllerImpl(checkpointService: CheckpointService) extends CheckpointController with BaseController { - override def createCheckpoint(checkpointDTO: CheckpointDTO): IO[ErrorResponse, CheckpointDTO] = { - serviceCallWithStatus[Unit, CheckpointDTO]( - checkpointService.saveCheckpoint(checkpointDTO), - _ => checkpointDTO + override def createCheckpoint( + checkpointDTO: CheckpointDTO + ): IO[ErrorResponse, SingleSuccessResponse[CheckpointDTO]] = { + mapToSingleSingleSuccessResponse( + serviceCallWithStatus[Unit, CheckpointDTO]( + checkpointService.saveCheckpoint(checkpointDTO), + _ => checkpointDTO + ) ) } diff --git a/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningController.scala b/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningController.scala index 0b2b7f817..62716096b 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningController.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningController.scala @@ -17,12 +17,18 @@ package za.co.absa.atum.server.api.controller import za.co.absa.atum.model.dto.{AdditionalDataSubmitDTO, AtumContextDTO, PartitioningSubmitDTO} -import za.co.absa.atum.server.model.ErrorResponse +import za.co.absa.atum.server.model.ErrorResponse.ErrorResponse +import za.co.absa.atum.server.model.SuccessResponse.SingleSuccessResponse import zio.IO import zio.macros.accessible @accessible trait PartitioningController { - def createPartitioningIfNotExists(partitioningSubmitDTO: PartitioningSubmitDTO): IO[ErrorResponse, AtumContextDTO] - def createOrUpdateAdditionalData(additionalData: AdditionalDataSubmitDTO): IO[ErrorResponse, AdditionalDataSubmitDTO] + def createPartitioningIfNotExists( + partitioningSubmitDTO: PartitioningSubmitDTO + ): IO[ErrorResponse, SingleSuccessResponse[AtumContextDTO]] + + def createOrUpdateAdditionalData( + additionalData: AdditionalDataSubmitDTO + ): IO[ErrorResponse, SingleSuccessResponse[AdditionalDataSubmitDTO]] } diff --git a/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningControllerImpl.scala b/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningControllerImpl.scala index 8be58cb19..071b30345 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningControllerImpl.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningControllerImpl.scala @@ -16,39 +16,47 @@ package za.co.absa.atum.server.api.controller - import za.co.absa.atum.model.dto.{AdditionalDataSubmitDTO, AtumContextDTO, PartitioningSubmitDTO} import za.co.absa.atum.server.api.exception.ServiceError import za.co.absa.atum.server.api.service.PartitioningService -import za.co.absa.atum.server.model.{ErrorResponse, InternalServerErrorResponse} +import za.co.absa.atum.server.model.ErrorResponse.{ErrorResponse, InternalServerErrorResponse} +import za.co.absa.atum.server.model.SuccessResponse.SingleSuccessResponse import zio._ class PartitioningControllerImpl(partitioningService: PartitioningService) - extends PartitioningController with BaseController { + extends PartitioningController + with BaseController { override def createPartitioningIfNotExists( partitioningSubmitDTO: PartitioningSubmitDTO - ): IO[ErrorResponse, AtumContextDTO] = { - for { - _ <- partitioningService.createPartitioningIfNotExists(partitioningSubmitDTO) + ): IO[ErrorResponse, SingleSuccessResponse[AtumContextDTO]] = { + val atumContextDTOEffect = for { + _ <- partitioningService + .createPartitioningIfNotExists(partitioningSubmitDTO) .mapError(serviceError => InternalServerErrorResponse(serviceError.message)) - measures <- partitioningService.getPartitioningMeasures(partitioningSubmitDTO.partitioning) - .mapError { - serviceError: ServiceError => InternalServerErrorResponse(serviceError.message) - } - additionalData <- partitioningService.getPartitioningAdditionalData(partitioningSubmitDTO.partitioning) - .mapError { - serviceError: ServiceError => InternalServerErrorResponse(serviceError.message) - } + measures <- partitioningService + .getPartitioningMeasures(partitioningSubmitDTO.partitioning) + .mapError { serviceError: ServiceError => + InternalServerErrorResponse(serviceError.message) + } + additionalData <- partitioningService + .getPartitioningAdditionalData(partitioningSubmitDTO.partitioning) + .mapError { serviceError: ServiceError => + InternalServerErrorResponse(serviceError.message) + } } yield AtumContextDTO(partitioningSubmitDTO.partitioning, measures.toSet, additionalData) + + mapToSingleSingleSuccessResponse(atumContextDTOEffect) } override def createOrUpdateAdditionalData( additionalData: AdditionalDataSubmitDTO - ): IO[ErrorResponse, AdditionalDataSubmitDTO] = { - serviceCallWithStatus[Unit, AdditionalDataSubmitDTO]( - partitioningService.createOrUpdateAdditionalData(additionalData), - _ => additionalData + ): IO[ErrorResponse, SingleSuccessResponse[AdditionalDataSubmitDTO]] = { + mapToSingleSingleSuccessResponse( + serviceCallWithStatus[Unit, AdditionalDataSubmitDTO]( + partitioningService.createOrUpdateAdditionalData(additionalData), + _ => additionalData + ) ) } diff --git a/server/src/main/scala/za/co/absa/atum/server/api/http/BaseEndpoints.scala b/server/src/main/scala/za/co/absa/atum/server/api/http/BaseEndpoints.scala index 92501f281..01ed5ff85 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/http/BaseEndpoints.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/http/BaseEndpoints.scala @@ -22,7 +22,7 @@ import sttp.tapir.json.play.jsonBody import sttp.tapir.ztapir._ import sttp.tapir.{EndpointOutput, PublicEndpoint} import za.co.absa.atum.server.Constants.Endpoints.{Api, V1} -import za.co.absa.atum.server.model._ +import za.co.absa.atum.server.model.ErrorResponse._ trait BaseEndpoints { diff --git a/server/src/main/scala/za/co/absa/atum/server/api/http/Endpoints.scala b/server/src/main/scala/za/co/absa/atum/server/api/http/Endpoints.scala index 7babe13dc..2b31d2a08 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/http/Endpoints.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/http/Endpoints.scala @@ -17,41 +17,43 @@ package za.co.absa.atum.server.api.http import sttp.model.StatusCode -import sttp.tapir.{PublicEndpoint, endpoint} import sttp.tapir.generic.auto.schemaForCaseClass import sttp.tapir.json.play.jsonBody import sttp.tapir.ztapir._ -import za.co.absa.atum.model.dto.{AtumContextDTO, CheckpointDTO, PartitioningSubmitDTO, AdditionalDataSubmitDTO} +import sttp.tapir.{PublicEndpoint, endpoint} +import za.co.absa.atum.model.dto.{AdditionalDataSubmitDTO, AtumContextDTO, CheckpointDTO, PartitioningSubmitDTO} import za.co.absa.atum.server.Constants.Endpoints._ -import za.co.absa.atum.server.model.ErrorResponse +import za.co.absa.atum.server.model.ErrorResponse.ErrorResponse import za.co.absa.atum.server.model.PlayJsonImplicits._ +import za.co.absa.atum.server.model.SuccessResponse.SingleSuccessResponse trait Endpoints extends BaseEndpoints { - protected val createCheckpointEndpoint: PublicEndpoint[CheckpointDTO, ErrorResponse, CheckpointDTO, Any] = { + protected val createCheckpointEndpoint + : PublicEndpoint[CheckpointDTO, ErrorResponse, SingleSuccessResponse[CheckpointDTO], Any] = { apiV1.post .in(CreateCheckpoint) .in(jsonBody[CheckpointDTO]) .out(statusCode(StatusCode.Created)) - .out(jsonBody[CheckpointDTO]) + .out(jsonBody[SingleSuccessResponse[CheckpointDTO]]) } protected val createPartitioningEndpoint - : PublicEndpoint[PartitioningSubmitDTO, ErrorResponse, AtumContextDTO, Any] = { + : PublicEndpoint[PartitioningSubmitDTO, ErrorResponse, SingleSuccessResponse[AtumContextDTO], Any] = { apiV1.post .in(CreatePartitioning) .in(jsonBody[PartitioningSubmitDTO]) .out(statusCode(StatusCode.Ok)) - .out(jsonBody[AtumContextDTO]) + .out(jsonBody[SingleSuccessResponse[AtumContextDTO]]) } protected val createOrUpdateAdditionalDataEndpoint - : PublicEndpoint[AdditionalDataSubmitDTO, ErrorResponse, AdditionalDataSubmitDTO, Any] = { + : PublicEndpoint[AdditionalDataSubmitDTO, ErrorResponse, SingleSuccessResponse[AdditionalDataSubmitDTO], Any] = { apiV1.post .in(CreateOrUpdateAdditionalData) .in(jsonBody[AdditionalDataSubmitDTO]) .out(statusCode(StatusCode.Ok)) - .out(jsonBody[AdditionalDataSubmitDTO]) + .out(jsonBody[SingleSuccessResponse[AdditionalDataSubmitDTO]]) } protected val zioMetricsEndpoint: PublicEndpoint[Unit, Unit, String, Any] = { diff --git a/server/src/main/scala/za/co/absa/atum/server/api/http/ServerOptions.scala b/server/src/main/scala/za/co/absa/atum/server/api/http/ServerOptions.scala index 226cebf8a..f6bbe79cd 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/http/ServerOptions.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/http/ServerOptions.scala @@ -27,7 +27,7 @@ import sttp.tapir.server.interceptor.decodefailure.DefaultDecodeFailureHandler.r import sttp.tapir.server.interceptor.metrics.MetricsRequestInterceptor import sttp.tapir.server.model.ValuedEndpointOutput import sttp.tapir.ztapir.{headers, statusCode} -import za.co.absa.atum.server.model.BadRequestResponse +import za.co.absa.atum.server.model.ErrorResponse.BadRequestResponse import zio.interop.catz._ trait ServerOptions { diff --git a/server/src/main/scala/za/co/absa/atum/server/model/ErrorResponse.scala b/server/src/main/scala/za/co/absa/atum/server/model/ErrorResponse.scala index 2fbc0c697..4869f4208 100644 --- a/server/src/main/scala/za/co/absa/atum/server/model/ErrorResponse.scala +++ b/server/src/main/scala/za/co/absa/atum/server/model/ErrorResponse.scala @@ -18,32 +18,28 @@ package za.co.absa.atum.server.model import play.api.libs.json.{Json, Reads, Writes} -sealed trait ErrorResponse { - def message: String -} - object ErrorResponse { + + sealed trait ErrorResponse { + def message: String + } + implicit val reads: Reads[ErrorResponse] = Json.reads[ErrorResponse] implicit val writes: Writes[ErrorResponse] = Json.writes[ErrorResponse] -} -final case class BadRequestResponse(message: String) extends ErrorResponse + final case class BadRequestResponse(message: String) extends ErrorResponse -object BadRequestResponse { - implicit val reads: Reads[BadRequestResponse] = Json.reads[BadRequestResponse] - implicit val writes: Writes[BadRequestResponse] = Json.writes[BadRequestResponse] -} + implicit val readsBadRequestResponse: Reads[BadRequestResponse] = Json.reads[BadRequestResponse] + implicit val writesBadRequestResponse: Writes[BadRequestResponse] = Json.writes[BadRequestResponse] -final case class GeneralErrorResponse(message: String) extends ErrorResponse + final case class GeneralErrorResponse(message: String) extends ErrorResponse -object GeneralErrorResponse { - implicit val reads: Reads[GeneralErrorResponse] = Json.reads[GeneralErrorResponse] - implicit val writes: Writes[GeneralErrorResponse] = Json.writes[GeneralErrorResponse] -} + implicit val readsGeneralErrorResponse: Reads[GeneralErrorResponse] = Json.reads[GeneralErrorResponse] + implicit val writesGeneralErrorResponse: Writes[GeneralErrorResponse] = Json.writes[GeneralErrorResponse] + + final case class InternalServerErrorResponse(message: String) extends ErrorResponse -final case class InternalServerErrorResponse(message: String) extends ErrorResponse + implicit val readsInternalServerErrorResponse: Reads[InternalServerErrorResponse] = Json.reads[InternalServerErrorResponse] + implicit val writesInternalServerErrorResponse: Writes[InternalServerErrorResponse] = Json.writes[InternalServerErrorResponse] -object InternalServerErrorResponse { - implicit val reads: Reads[InternalServerErrorResponse] = Json.reads[InternalServerErrorResponse] - implicit val writes: Writes[InternalServerErrorResponse] = Json.writes[InternalServerErrorResponse] } diff --git a/server/src/main/scala/za/co/absa/atum/server/model/PlayJsonImplicits.scala b/server/src/main/scala/za/co/absa/atum/server/model/PlayJsonImplicits.scala index 03a3776df..c567be3fb 100644 --- a/server/src/main/scala/za/co/absa/atum/server/model/PlayJsonImplicits.scala +++ b/server/src/main/scala/za/co/absa/atum/server/model/PlayJsonImplicits.scala @@ -20,6 +20,7 @@ import play.api.libs.functional.syntax.toFunctionalBuilderOps import play.api.libs.json._ import za.co.absa.atum.model.dto.MeasureResultDTO.{ResultValueType, TypedValue} import za.co.absa.atum.model.dto._ +import za.co.absa.atum.server.model.SuccessResponse.SingleSuccessResponse object PlayJsonImplicits { @@ -93,4 +94,7 @@ object PlayJsonImplicits { implicit val readsAtumContextDTO: Reads[AtumContextDTO] = Json.reads[AtumContextDTO] implicit val writesAtumContextDTO: Writes[AtumContextDTO] = Json.writes[AtumContextDTO] + implicit def readsSingleApiResponse[T: Reads]: Reads[SingleSuccessResponse[T]] = Json.reads[SingleSuccessResponse[T]] + implicit def writesSingleApiResponse[T: Writes]: Writes[SingleSuccessResponse[T]] = Json.writes[SingleSuccessResponse[T]] + } diff --git a/server/src/main/scala/za/co/absa/atum/server/model/SuccessResponse.scala b/server/src/main/scala/za/co/absa/atum/server/model/SuccessResponse.scala new file mode 100644 index 000000000..90440a0bb --- /dev/null +++ b/server/src/main/scala/za/co/absa/atum/server/model/SuccessResponse.scala @@ -0,0 +1,26 @@ +/* + * Copyright 2021 ABSA Group Limited + * + * 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 za.co.absa.atum.server.model + +object SuccessResponse { + + sealed trait SuccessResponse + + case class SingleSuccessResponse[T](data: T) extends SuccessResponse + case class MultiSuccessResponse[T](data: Seq[T]) extends SuccessResponse + +} diff --git a/server/src/test/scala/za/co/absa/atum/server/api/controller/CheckpointControllerSpec.scala b/server/src/test/scala/za/co/absa/atum/server/api/controller/CheckpointControllerSpec.scala index 04f6ba670..b7adcebb0 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/controller/CheckpointControllerSpec.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/controller/CheckpointControllerSpec.scala @@ -16,21 +16,19 @@ package za.co.absa.atum.server.api.controller -import org.junit.runner.RunWith import org.mockito.Mockito.{mock, when} import za.co.absa.atum.server.api.TestData import za.co.absa.atum.server.api.exception.ServiceError import za.co.absa.atum.server.api.service.CheckpointService -import za.co.absa.atum.server.model.{GeneralErrorResponse, InternalServerErrorResponse} +import za.co.absa.atum.server.model.ErrorResponse.{GeneralErrorResponse, InternalServerErrorResponse} +import za.co.absa.atum.server.model.SuccessResponse.SingleSuccessResponse import za.co.absa.fadb.exceptions.ErrorInDataException import za.co.absa.fadb.status.FunctionStatus -import zio.test.Assertion.failsWithA import zio._ +import zio.test.Assertion.failsWithA import zio.test._ -import zio.test.junit.ZTestJUnitRunner -@RunWith(classOf[ZTestJUnitRunner]) -class CheckpointControllerSpec extends ZIOSpecDefault with TestData { +object CheckpointControllerSpec extends ZIOSpecDefault with TestData { private val checkpointServiceMock = mock(classOf[CheckpointService]) @@ -49,7 +47,7 @@ class CheckpointControllerSpec extends ZIOSpecDefault with TestData { test("Returns expected CheckpointDTO") { for { result <- CheckpointController.createCheckpoint(checkpointDTO1) - } yield assertTrue(result == checkpointDTO1) + } yield assertTrue(result == SingleSuccessResponse(checkpointDTO1)) }, test("Returns expected InternalServerErrorResponse") { assertZIO(CheckpointController.createCheckpoint(checkpointDTO3).exit)(failsWithA[InternalServerErrorResponse]) diff --git a/server/src/test/scala/za/co/absa/atum/server/api/controller/PartitioningControllerSpec.scala b/server/src/test/scala/za/co/absa/atum/server/api/controller/PartitioningControllerSpec.scala index 2295a5b24..46df42935 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/controller/PartitioningControllerSpec.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/controller/PartitioningControllerSpec.scala @@ -1,27 +1,28 @@ /* -* Copyright 2021 ABSA Group Limited -* -* 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. -*/ + * Copyright 2021 ABSA Group Limited + * + * 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 za.co.absa.atum.server.api.controller import org.mockito.Mockito.{mock, when} import za.co.absa.atum.server.api.TestData import za.co.absa.atum.server.api.exception.ServiceError import za.co.absa.atum.server.api.service.PartitioningService -import za.co.absa.atum.server.model.InternalServerErrorResponse -import zio.test.Assertion.{equalTo, failsWithA} +import za.co.absa.atum.server.model.ErrorResponse.InternalServerErrorResponse +import za.co.absa.atum.server.model.SuccessResponse.SingleSuccessResponse import zio._ +import zio.test.Assertion.{equalTo, failsWithA} import zio.test._ object PartitioningControllerSpec extends ZIOSpecDefault with TestData { @@ -46,7 +47,7 @@ object PartitioningControllerSpec extends ZIOSpecDefault with TestData { test("Returns expected AtumContextDTO") { for { result <- PartitioningController.createPartitioningIfNotExists(partitioningSubmitDTO1) - } yield assertTrue (result == atumContextDTO1) + } yield assertTrue(result == SingleSuccessResponse(atumContextDTO1)) }, test("Returns expected InternalServerErrorResponse") { assertZIO(PartitioningController.createPartitioningIfNotExists(partitioningSubmitDTO2).exit)( @@ -56,9 +57,11 @@ object PartitioningControllerSpec extends ZIOSpecDefault with TestData { ), suite("CreateOrUpdateAdditionalDataSuite")( test("Returns expected AdditionalDataSubmitDTO") { - assertZIO(PartitioningController.createOrUpdateAdditionalData(additionalDataSubmitDTO1))(equalTo(additionalDataSubmitDTO1)) + assertZIO(PartitioningController.createOrUpdateAdditionalData(additionalDataSubmitDTO1))( + equalTo(SingleSuccessResponse(additionalDataSubmitDTO1)) + ) }, - test ("Returns expected InternalServerErrorResponse") { + test("Returns expected InternalServerErrorResponse") { assertZIO(PartitioningController.createOrUpdateAdditionalData(additionalDataSubmitDTO2).exit)( failsWithA[InternalServerErrorResponse] ) diff --git a/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointSpec.scala b/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointSpec.scala index 51c3bb8d2..77c0dae4b 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointSpec.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointSpec.scala @@ -18,26 +18,27 @@ package za.co.absa.atum.server.api.http import org.mockito.Mockito.{mock, when} import sttp.client3._ -import sttp.client3.testing.SttpBackendStub import sttp.client3.playJson._ +import sttp.client3.testing.SttpBackendStub import sttp.model.StatusCode import sttp.tapir.server.stub.TapirStubInterpreter import sttp.tapir.ztapir.{RIOMonadError, RichZEndpoint} import za.co.absa.atum.model.dto.CheckpointDTO import za.co.absa.atum.server.api.TestData import za.co.absa.atum.server.api.controller.CheckpointController -import za.co.absa.atum.server.model.{GeneralErrorResponse, InternalServerErrorResponse} -import zio.test._ -import zio._ +import za.co.absa.atum.server.model.ErrorResponse.{GeneralErrorResponse, InternalServerErrorResponse} import za.co.absa.atum.server.model.PlayJsonImplicits.{readsCheckpointDTO, writesCheckpointDTO} +import za.co.absa.atum.server.model.SuccessResponse.SingleSuccessResponse +import zio._ import zio.test.Assertion.equalTo +import zio.test._ object CreateCheckpointEndpointSpec extends ZIOSpecDefault with Endpoints with TestData { private val checkpointControllerMock = mock(classOf[CheckpointController]) when(checkpointControllerMock.createCheckpoint(checkpointDTO1)) - .thenReturn(ZIO.succeed(checkpointDTO1)) + .thenReturn(ZIO.succeed(SingleSuccessResponse(checkpointDTO1))) when(checkpointControllerMock.createCheckpoint(checkpointDTO2)) .thenReturn(ZIO.fail(GeneralErrorResponse("error"))) when(checkpointControllerMock.createCheckpoint(checkpointDTO3)) diff --git a/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointSpec.scala b/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointSpec.scala index 7a73733b9..eb3d74515 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointSpec.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointSpec.scala @@ -26,18 +26,19 @@ import sttp.tapir.ztapir.{RIOMonadError, RichZEndpoint} import za.co.absa.atum.model.dto.AtumContextDTO import za.co.absa.atum.server.api.TestData import za.co.absa.atum.server.api.controller.PartitioningController -import za.co.absa.atum.server.model.{GeneralErrorResponse, InternalServerErrorResponse} -import zio.test.Assertion.equalTo +import za.co.absa.atum.server.model.ErrorResponse.{GeneralErrorResponse, InternalServerErrorResponse} +import za.co.absa.atum.server.model.PlayJsonImplicits.{readsAtumContextDTO, writesPartitioningSubmitDTO} +import za.co.absa.atum.server.model.SuccessResponse.SingleSuccessResponse import zio._ +import zio.test.Assertion.equalTo import zio.test._ -import za.co.absa.atum.server.model.PlayJsonImplicits.{readsAtumContextDTO, writesPartitioningSubmitDTO} object CreatePartitioningEndpointSpec extends ZIOSpecDefault with Endpoints with TestData { private val createPartitioningEndpointMock = mock(classOf[PartitioningController]) when(createPartitioningEndpointMock.createPartitioningIfNotExists(partitioningSubmitDTO1)) - .thenReturn(ZIO.succeed(createAtumContextDTO(partitioningSubmitDTO1))) + .thenReturn(ZIO.succeed(SingleSuccessResponse(createAtumContextDTO(partitioningSubmitDTO1)))) when(createPartitioningEndpointMock.createPartitioningIfNotExists(partitioningSubmitDTO2)) .thenReturn(ZIO.fail(GeneralErrorResponse("error"))) when(createPartitioningEndpointMock.createPartitioningIfNotExists(partitioningSubmitDTO3)) From 45adbfc047f0022b5dd8610f342a288d7df7ea31 Mon Sep 17 00:00:00 2001 From: Pavel Salamon Date: Wed, 22 May 2024 10:29:41 +0200 Subject: [PATCH 02/25] fix tests --- .../server/api/http/CreateCheckpointEndpointSpec.scala | 8 +++++--- .../server/api/http/CreatePartitioningEndpointSpec.scala | 4 +++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointSpec.scala b/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointSpec.scala index 77c0dae4b..114904e35 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointSpec.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointSpec.scala @@ -28,7 +28,7 @@ import za.co.absa.atum.server.api.TestData import za.co.absa.atum.server.api.controller.CheckpointController import za.co.absa.atum.server.model.ErrorResponse.{GeneralErrorResponse, InternalServerErrorResponse} import za.co.absa.atum.server.model.PlayJsonImplicits.{readsCheckpointDTO, writesCheckpointDTO} -import za.co.absa.atum.server.model.SuccessResponse.SingleSuccessResponse +import za.co.absa.atum.server.model.SuccessResponse.{SingleSuccessResponse, mapToSingleSingleSuccessResponse} import zio._ import zio.test.Assertion.equalTo import zio.test._ @@ -47,7 +47,9 @@ object CreateCheckpointEndpointSpec extends ZIOSpecDefault with Endpoints with T private val checkpointControllerMockLayer = ZLayer.succeed(checkpointControllerMock) private val createCheckpointServerEndpoint = - createCheckpointEndpoint.zServerLogic(CheckpointController.createCheckpoint) + createCheckpointEndpoint.zServerLogic( + CheckpointController.createCheckpoint _ andThen(_.map(SingleSuccessResponse(_))) + ) def spec: Spec[TestEnvironment with Scope, Any] = { val backendStub = TapirStubInterpreter(SttpBackendStub.apply(new RIOMonadError[CheckpointController])) @@ -68,7 +70,7 @@ object CreateCheckpointEndpointSpec extends ZIOSpecDefault with Endpoints with T val body = response.map(_.body) val statusCode = response.map(_.code) - assertZIO(body <&> statusCode)(equalTo(Right(checkpointDTO1), StatusCode.Created)) + assertZIO(body <&> statusCode)(equalTo(Right(SingleSuccessResponse(checkpointDTO1)), StatusCode.Created)) }, test("Returns expected BadRequest") { val response = request diff --git a/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointSpec.scala b/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointSpec.scala index eb3d74515..01c7263fc 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointSpec.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointSpec.scala @@ -47,7 +47,9 @@ object CreatePartitioningEndpointSpec extends ZIOSpecDefault with Endpoints with private val createPartitioningEndpointMockLayer = ZLayer.succeed(createPartitioningEndpointMock) private val createPartitioningServerEndpoint = - createPartitioningEndpoint.zServerLogic(PartitioningController.createPartitioningIfNotExists) + createPartitioningEndpoint.zServerLogic( + PartitioningController.createPartitioningIfNotExists _ andThen (_.map(SingleSuccessResponse(_))) + ) def spec: Spec[TestEnvironment with Scope, Any] = { val backendStub = TapirStubInterpreter(SttpBackendStub.apply(new RIOMonadError[PartitioningController])) From 38a9668a78cbc336a6f0d02bb38fd924707e7963 Mon Sep 17 00:00:00 2001 From: Pavel Salamon Date: Wed, 22 May 2024 10:33:36 +0200 Subject: [PATCH 03/25] fix tests --- .../atum/server/api/http/CreateCheckpointEndpointSpec.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointSpec.scala b/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointSpec.scala index 114904e35..eaf5c0446 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointSpec.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointSpec.scala @@ -28,7 +28,7 @@ import za.co.absa.atum.server.api.TestData import za.co.absa.atum.server.api.controller.CheckpointController import za.co.absa.atum.server.model.ErrorResponse.{GeneralErrorResponse, InternalServerErrorResponse} import za.co.absa.atum.server.model.PlayJsonImplicits.{readsCheckpointDTO, writesCheckpointDTO} -import za.co.absa.atum.server.model.SuccessResponse.{SingleSuccessResponse, mapToSingleSingleSuccessResponse} +import za.co.absa.atum.server.model.SuccessResponse.SingleSuccessResponse import zio._ import zio.test.Assertion.equalTo import zio.test._ From 34cfee059d2daec7ce071c2c760f32842d9b36cf Mon Sep 17 00:00:00 2001 From: Pavel Salamon Date: Wed, 22 May 2024 10:37:11 +0200 Subject: [PATCH 04/25] fix tests --- .../atum/server/api/http/CreateCheckpointEndpointSpec.scala | 3 ++- .../atum/server/api/http/CreatePartitioningEndpointSpec.scala | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointSpec.scala b/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointSpec.scala index eaf5c0446..e34264eb5 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointSpec.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointSpec.scala @@ -48,7 +48,8 @@ object CreateCheckpointEndpointSpec extends ZIOSpecDefault with Endpoints with T private val createCheckpointServerEndpoint = createCheckpointEndpoint.zServerLogic( - CheckpointController.createCheckpoint _ andThen(_.map(SingleSuccessResponse(_))) + CheckpointController.createCheckpoint +// CheckpointController.createCheckpoint _ andThen(_.map(SingleSuccessResponse(_))) ) def spec: Spec[TestEnvironment with Scope, Any] = { diff --git a/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointSpec.scala b/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointSpec.scala index 01c7263fc..b3a66f7e2 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointSpec.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointSpec.scala @@ -48,7 +48,8 @@ object CreatePartitioningEndpointSpec extends ZIOSpecDefault with Endpoints with private val createPartitioningServerEndpoint = createPartitioningEndpoint.zServerLogic( - PartitioningController.createPartitioningIfNotExists _ andThen (_.map(SingleSuccessResponse(_))) +// PartitioningController.createPartitioningIfNotExists _ andThen (_.map(SingleSuccessResponse(_))) + PartitioningController.createPartitioningIfNotExists ) def spec: Spec[TestEnvironment with Scope, Any] = { From 3f09ecf4d4bf669d14dc113c83d8a65ce1a10d97 Mon Sep 17 00:00:00 2001 From: Pavel Salamon Date: Wed, 22 May 2024 11:08:18 +0200 Subject: [PATCH 05/25] fixes, minors --- .../absa/atum/server/model/PlayJsonImplicits.scala | 4 ++-- .../api/controller/PartitioningControllerSpec.scala | 3 ++- .../api/http/CreateCheckpointEndpointSpec.scala | 11 ++++------- .../api/http/CreatePartitioningEndpointSpec.scala | 13 ++++++------- 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/server/src/main/scala/za/co/absa/atum/server/model/PlayJsonImplicits.scala b/server/src/main/scala/za/co/absa/atum/server/model/PlayJsonImplicits.scala index c567be3fb..d900e5441 100644 --- a/server/src/main/scala/za/co/absa/atum/server/model/PlayJsonImplicits.scala +++ b/server/src/main/scala/za/co/absa/atum/server/model/PlayJsonImplicits.scala @@ -94,7 +94,7 @@ object PlayJsonImplicits { implicit val readsAtumContextDTO: Reads[AtumContextDTO] = Json.reads[AtumContextDTO] implicit val writesAtumContextDTO: Writes[AtumContextDTO] = Json.writes[AtumContextDTO] - implicit def readsSingleApiResponse[T: Reads]: Reads[SingleSuccessResponse[T]] = Json.reads[SingleSuccessResponse[T]] - implicit def writesSingleApiResponse[T: Writes]: Writes[SingleSuccessResponse[T]] = Json.writes[SingleSuccessResponse[T]] + implicit def readsSingleSuccessResponse[T: Reads]: Reads[SingleSuccessResponse[T]] = Json.reads[SingleSuccessResponse[T]] + implicit def writesSingleSuccessResponse[T: Writes]: Writes[SingleSuccessResponse[T]] = Json.writes[SingleSuccessResponse[T]] } diff --git a/server/src/test/scala/za/co/absa/atum/server/api/controller/PartitioningControllerSpec.scala b/server/src/test/scala/za/co/absa/atum/server/api/controller/PartitioningControllerSpec.scala index 46df42935..c0e11f45e 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/controller/PartitioningControllerSpec.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/controller/PartitioningControllerSpec.scala @@ -5,7 +5,7 @@ * 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 + * 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, @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package za.co.absa.atum.server.api.controller import org.mockito.Mockito.{mock, when} diff --git a/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointSpec.scala b/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointSpec.scala index e34264eb5..7400c506f 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointSpec.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointSpec.scala @@ -27,7 +27,7 @@ import za.co.absa.atum.model.dto.CheckpointDTO import za.co.absa.atum.server.api.TestData import za.co.absa.atum.server.api.controller.CheckpointController import za.co.absa.atum.server.model.ErrorResponse.{GeneralErrorResponse, InternalServerErrorResponse} -import za.co.absa.atum.server.model.PlayJsonImplicits.{readsCheckpointDTO, writesCheckpointDTO} +import za.co.absa.atum.server.model.PlayJsonImplicits._ import za.co.absa.atum.server.model.SuccessResponse.SingleSuccessResponse import zio._ import zio.test.Assertion.equalTo @@ -47,10 +47,7 @@ object CreateCheckpointEndpointSpec extends ZIOSpecDefault with Endpoints with T private val checkpointControllerMockLayer = ZLayer.succeed(checkpointControllerMock) private val createCheckpointServerEndpoint = - createCheckpointEndpoint.zServerLogic( - CheckpointController.createCheckpoint -// CheckpointController.createCheckpoint _ andThen(_.map(SingleSuccessResponse(_))) - ) + createCheckpointEndpoint.zServerLogic(CheckpointController.createCheckpoint) def spec: Spec[TestEnvironment with Scope, Any] = { val backendStub = TapirStubInterpreter(SttpBackendStub.apply(new RIOMonadError[CheckpointController])) @@ -60,7 +57,7 @@ object CreateCheckpointEndpointSpec extends ZIOSpecDefault with Endpoints with T val request = basicRequest .post(uri"https://test.com/api/v1/createCheckpoint") - .response(asJson[CheckpointDTO]) + .response(asJson[SingleSuccessResponse[CheckpointDTO]]) suite("CreateCheckpointEndpointSuite")( test("Returns expected CheckpointDTO") { @@ -71,7 +68,7 @@ object CreateCheckpointEndpointSpec extends ZIOSpecDefault with Endpoints with T val body = response.map(_.body) val statusCode = response.map(_.code) - assertZIO(body <&> statusCode)(equalTo(Right(SingleSuccessResponse(checkpointDTO1)), StatusCode.Created)) + assertZIO(body <*> statusCode)(equalTo(Right(SingleSuccessResponse(checkpointDTO1)), StatusCode.Created)) }, test("Returns expected BadRequest") { val response = request diff --git a/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointSpec.scala b/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointSpec.scala index b3a66f7e2..8e8a7821e 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointSpec.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointSpec.scala @@ -27,7 +27,7 @@ import za.co.absa.atum.model.dto.AtumContextDTO import za.co.absa.atum.server.api.TestData import za.co.absa.atum.server.api.controller.PartitioningController import za.co.absa.atum.server.model.ErrorResponse.{GeneralErrorResponse, InternalServerErrorResponse} -import za.co.absa.atum.server.model.PlayJsonImplicits.{readsAtumContextDTO, writesPartitioningSubmitDTO} +import za.co.absa.atum.server.model.PlayJsonImplicits._ import za.co.absa.atum.server.model.SuccessResponse.SingleSuccessResponse import zio._ import zio.test.Assertion.equalTo @@ -47,10 +47,7 @@ object CreatePartitioningEndpointSpec extends ZIOSpecDefault with Endpoints with private val createPartitioningEndpointMockLayer = ZLayer.succeed(createPartitioningEndpointMock) private val createPartitioningServerEndpoint = - createPartitioningEndpoint.zServerLogic( -// PartitioningController.createPartitioningIfNotExists _ andThen (_.map(SingleSuccessResponse(_))) - PartitioningController.createPartitioningIfNotExists - ) + createPartitioningEndpoint.zServerLogic(PartitioningController.createPartitioningIfNotExists) def spec: Spec[TestEnvironment with Scope, Any] = { val backendStub = TapirStubInterpreter(SttpBackendStub.apply(new RIOMonadError[PartitioningController])) @@ -60,7 +57,7 @@ object CreatePartitioningEndpointSpec extends ZIOSpecDefault with Endpoints with val request = basicRequest .post(uri"https://test.com/api/v1/createPartitioning") - .response(asJson[AtumContextDTO]) + .response(asJson[SingleSuccessResponse[AtumContextDTO]]) suite("CreatePartitioningEndpointSuite")( test("Returns expected AtumContextDTO") { @@ -71,7 +68,9 @@ object CreatePartitioningEndpointSpec extends ZIOSpecDefault with Endpoints with val body = response.map(_.body) val statusCode = response.map(_.code) - assertZIO(body <&> statusCode)(equalTo(Right(createAtumContextDTO(partitioningSubmitDTO1)), StatusCode.Ok)) + assertZIO(body <&> statusCode)( + equalTo(Right(SingleSuccessResponse(createAtumContextDTO(partitioningSubmitDTO1))), StatusCode.Ok) + ) }, test("Returns expected BadRequest") { val response = request From 8fc40ba563c0b6fdca2b1a8d9c7d8067d716da89 Mon Sep 17 00:00:00 2001 From: Pavel Salamon Date: Wed, 22 May 2024 11:12:46 +0200 Subject: [PATCH 06/25] typo --- .../atum/server/api/http/CreateCheckpointEndpointSpec.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointSpec.scala b/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointSpec.scala index 7400c506f..faff93a4b 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointSpec.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointSpec.scala @@ -68,7 +68,7 @@ object CreateCheckpointEndpointSpec extends ZIOSpecDefault with Endpoints with T val body = response.map(_.body) val statusCode = response.map(_.code) - assertZIO(body <*> statusCode)(equalTo(Right(SingleSuccessResponse(checkpointDTO1)), StatusCode.Created)) + assertZIO(body <&> statusCode)(equalTo(Right(SingleSuccessResponse(checkpointDTO1)), StatusCode.Created)) }, test("Returns expected BadRequest") { val response = request From 57cb8507d5f2ce7af95ae29fe07a2c0720329532 Mon Sep 17 00:00:00 2001 From: Pavel Salamon Date: Wed, 22 May 2024 11:24:10 +0200 Subject: [PATCH 07/25] typo --- .../co/absa/atum/server/api/controller/BaseController.scala | 4 ++-- .../atum/server/api/controller/CheckpointControllerImpl.scala | 2 +- .../server/api/controller/PartitioningControllerImpl.scala | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/server/src/main/scala/za/co/absa/atum/server/api/controller/BaseController.scala b/server/src/main/scala/za/co/absa/atum/server/api/controller/BaseController.scala index 9a3fa7df8..6a123c8f0 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/controller/BaseController.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/controller/BaseController.scala @@ -42,13 +42,13 @@ trait BaseController { } - protected def mapToSingleSingleSuccessResponse[A]( + protected def mapToSingleSuccessResponse[A]( effect: IO[ErrorResponse, A] ): IO[ErrorResponse, SingleSuccessResponse[A]] = { effect.map(SingleSuccessResponse(_)) } - protected def mapToSingleMultiSuccessResponse[A]( + protected def mapToMultiSuccessResponse[A]( effect: IO[ErrorResponse, Seq[A]] ): IO[ErrorResponse, MultiSuccessResponse[A]] = { effect.map(MultiSuccessResponse(_)) diff --git a/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointControllerImpl.scala b/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointControllerImpl.scala index d7757d034..a03e56ad7 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointControllerImpl.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointControllerImpl.scala @@ -27,7 +27,7 @@ class CheckpointControllerImpl(checkpointService: CheckpointService) extends Che override def createCheckpoint( checkpointDTO: CheckpointDTO ): IO[ErrorResponse, SingleSuccessResponse[CheckpointDTO]] = { - mapToSingleSingleSuccessResponse( + mapToSingleSuccessResponse( serviceCallWithStatus[Unit, CheckpointDTO]( checkpointService.saveCheckpoint(checkpointDTO), _ => checkpointDTO diff --git a/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningControllerImpl.scala b/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningControllerImpl.scala index 071b30345..1c078a234 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningControllerImpl.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningControllerImpl.scala @@ -46,13 +46,13 @@ class PartitioningControllerImpl(partitioningService: PartitioningService) } } yield AtumContextDTO(partitioningSubmitDTO.partitioning, measures.toSet, additionalData) - mapToSingleSingleSuccessResponse(atumContextDTOEffect) + mapToSingleSuccessResponse(atumContextDTOEffect) } override def createOrUpdateAdditionalData( additionalData: AdditionalDataSubmitDTO ): IO[ErrorResponse, SingleSuccessResponse[AdditionalDataSubmitDTO]] = { - mapToSingleSingleSuccessResponse( + mapToSingleSuccessResponse( serviceCallWithStatus[Unit, AdditionalDataSubmitDTO]( partitioningService.createOrUpdateAdditionalData(additionalData), _ => additionalData From 03a01910c80a2d1646a097c7de32af81944a2816 Mon Sep 17 00:00:00 2001 From: Pavel Salamon Date: Fri, 24 May 2024 09:04:54 +0200 Subject: [PATCH 08/25] merge conflicts resolved --- .../api/controller/CheckpointControllerIntegrationTests.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/src/test/scala/za/co/absa/atum/server/api/controller/CheckpointControllerIntegrationTests.scala b/server/src/test/scala/za/co/absa/atum/server/api/controller/CheckpointControllerIntegrationTests.scala index 1aacdc8af..de098d2e6 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/controller/CheckpointControllerIntegrationTests.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/controller/CheckpointControllerIntegrationTests.scala @@ -20,7 +20,8 @@ import org.mockito.Mockito.{mock, when} import za.co.absa.atum.server.api.TestData import za.co.absa.atum.server.api.exception.ServiceError import za.co.absa.atum.server.api.service.CheckpointService -import za.co.absa.atum.server.model.{GeneralErrorResponse, InternalServerErrorResponse} +import za.co.absa.atum.server.model.ErrorResponse.{GeneralErrorResponse, InternalServerErrorResponse} +import za.co.absa.atum.server.model.SuccessResponse.SingleSuccessResponse import za.co.absa.fadb.exceptions.ErrorInDataException import za.co.absa.fadb.status.FunctionStatus import zio.test.Assertion.failsWithA From 9c307b8631cf18a5dfd88790cdb8772bc9a38355 Mon Sep 17 00:00:00 2001 From: Pavel Salamon Date: Fri, 24 May 2024 15:03:34 +0200 Subject: [PATCH 09/25] reads to format for Single/MultiSuccessResponse --- .../za/co/absa/atum/server/model/PlayJsonImplicits.scala | 6 +++--- ...scala => CreateCheckpointEndpointIntegrationTests.scala} | 0 2 files changed, 3 insertions(+), 3 deletions(-) rename server/src/test/scala/za/co/absa/atum/server/api/http/{CreateCheckpointEndpointIntegrationTest.scala => CreateCheckpointEndpointIntegrationTests.scala} (100%) diff --git a/server/src/main/scala/za/co/absa/atum/server/model/PlayJsonImplicits.scala b/server/src/main/scala/za/co/absa/atum/server/model/PlayJsonImplicits.scala index d900e5441..77dc63c34 100644 --- a/server/src/main/scala/za/co/absa/atum/server/model/PlayJsonImplicits.scala +++ b/server/src/main/scala/za/co/absa/atum/server/model/PlayJsonImplicits.scala @@ -20,7 +20,7 @@ import play.api.libs.functional.syntax.toFunctionalBuilderOps import play.api.libs.json._ import za.co.absa.atum.model.dto.MeasureResultDTO.{ResultValueType, TypedValue} import za.co.absa.atum.model.dto._ -import za.co.absa.atum.server.model.SuccessResponse.SingleSuccessResponse +import za.co.absa.atum.server.model.SuccessResponse.{MultiSuccessResponse, SingleSuccessResponse} object PlayJsonImplicits { @@ -94,7 +94,7 @@ object PlayJsonImplicits { implicit val readsAtumContextDTO: Reads[AtumContextDTO] = Json.reads[AtumContextDTO] implicit val writesAtumContextDTO: Writes[AtumContextDTO] = Json.writes[AtumContextDTO] - implicit def readsSingleSuccessResponse[T: Reads]: Reads[SingleSuccessResponse[T]] = Json.reads[SingleSuccessResponse[T]] - implicit def writesSingleSuccessResponse[T: Writes]: Writes[SingleSuccessResponse[T]] = Json.writes[SingleSuccessResponse[T]] + implicit def formatSingleSuccessResponse[T: Format]: Format[SingleSuccessResponse[T]] = Json.format[SingleSuccessResponse[T]] + implicit def formatMultiSuccessResponse[T: Format]: Format[MultiSuccessResponse[T]] = Json.format[MultiSuccessResponse[T]] } diff --git a/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointIntegrationTest.scala b/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointIntegrationTests.scala similarity index 100% rename from server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointIntegrationTest.scala rename to server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointIntegrationTests.scala From 7933f7e2ea461f0889d2a742ebe5d810778b8dda Mon Sep 17 00:00:00 2001 From: Pavel Salamon Date: Mon, 27 May 2024 13:13:37 +0200 Subject: [PATCH 10/25] requestId, ResponseEnvelope --- .../atum/server/model/ErrorResponse.scala | 19 ++++++++++----- .../atum/server/model/ResponseEnvelope.scala | 23 +++++++++++++++++++ .../atum/server/model/SuccessResponse.scala | 11 ++++++--- 3 files changed, 44 insertions(+), 9 deletions(-) create mode 100644 server/src/main/scala/za/co/absa/atum/server/model/ResponseEnvelope.scala diff --git a/server/src/main/scala/za/co/absa/atum/server/model/ErrorResponse.scala b/server/src/main/scala/za/co/absa/atum/server/model/ErrorResponse.scala index 4869f4208..3ce5aabe4 100644 --- a/server/src/main/scala/za/co/absa/atum/server/model/ErrorResponse.scala +++ b/server/src/main/scala/za/co/absa/atum/server/model/ErrorResponse.scala @@ -18,28 +18,35 @@ package za.co.absa.atum.server.model import play.api.libs.json.{Json, Reads, Writes} +import java.util.UUID + object ErrorResponse { - sealed trait ErrorResponse { + sealed trait ErrorResponse extends ResponseEnvelope { def message: String } implicit val reads: Reads[ErrorResponse] = Json.reads[ErrorResponse] implicit val writes: Writes[ErrorResponse] = Json.writes[ErrorResponse] - final case class BadRequestResponse(message: String) extends ErrorResponse + final case class BadRequestResponse(message: String, override val requestId: UUID = UUID.randomUUID()) + extends ErrorResponse implicit val readsBadRequestResponse: Reads[BadRequestResponse] = Json.reads[BadRequestResponse] implicit val writesBadRequestResponse: Writes[BadRequestResponse] = Json.writes[BadRequestResponse] - final case class GeneralErrorResponse(message: String) extends ErrorResponse + final case class GeneralErrorResponse(message: String, override val requestId: UUID = UUID.randomUUID()) + extends ErrorResponse implicit val readsGeneralErrorResponse: Reads[GeneralErrorResponse] = Json.reads[GeneralErrorResponse] implicit val writesGeneralErrorResponse: Writes[GeneralErrorResponse] = Json.writes[GeneralErrorResponse] - final case class InternalServerErrorResponse(message: String) extends ErrorResponse + final case class InternalServerErrorResponse(message: String, override val requestId: UUID = UUID.randomUUID()) + extends ErrorResponse - implicit val readsInternalServerErrorResponse: Reads[InternalServerErrorResponse] = Json.reads[InternalServerErrorResponse] - implicit val writesInternalServerErrorResponse: Writes[InternalServerErrorResponse] = Json.writes[InternalServerErrorResponse] + implicit val readsInternalServerErrorResponse: Reads[InternalServerErrorResponse] = + Json.reads[InternalServerErrorResponse] + implicit val writesInternalServerErrorResponse: Writes[InternalServerErrorResponse] = + Json.writes[InternalServerErrorResponse] } diff --git a/server/src/main/scala/za/co/absa/atum/server/model/ResponseEnvelope.scala b/server/src/main/scala/za/co/absa/atum/server/model/ResponseEnvelope.scala new file mode 100644 index 000000000..8fb991d7c --- /dev/null +++ b/server/src/main/scala/za/co/absa/atum/server/model/ResponseEnvelope.scala @@ -0,0 +1,23 @@ +/* + * Copyright 2021 ABSA Group Limited + * + * 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 za.co.absa.atum.server.model + +import java.util.UUID + +trait ResponseEnvelope { + def requestId: UUID +} diff --git a/server/src/main/scala/za/co/absa/atum/server/model/SuccessResponse.scala b/server/src/main/scala/za/co/absa/atum/server/model/SuccessResponse.scala index 90440a0bb..5320a22f8 100644 --- a/server/src/main/scala/za/co/absa/atum/server/model/SuccessResponse.scala +++ b/server/src/main/scala/za/co/absa/atum/server/model/SuccessResponse.scala @@ -16,11 +16,16 @@ package za.co.absa.atum.server.model +import java.util.UUID + object SuccessResponse { - sealed trait SuccessResponse + sealed trait SuccessResponse extends ResponseEnvelope + + case class SingleSuccessResponse[T](data: T, override val requestId: UUID = UUID.randomUUID()) + extends SuccessResponse - case class SingleSuccessResponse[T](data: T) extends SuccessResponse - case class MultiSuccessResponse[T](data: Seq[T]) extends SuccessResponse + case class MultiSuccessResponse[T](data: Seq[T], override val requestId: UUID = UUID.randomUUID()) + extends SuccessResponse } From 976d3bfa069f6bdfe775131ae736911324db8eee Mon Sep 17 00:00:00 2001 From: Pavel Salamon Date: Mon, 27 May 2024 13:21:21 +0200 Subject: [PATCH 11/25] envelopes only for v2 endpoints --- .../server/api/controller/CheckpointController.scala | 3 ++- .../api/controller/CheckpointControllerImpl.scala | 7 ++++--- .../api/controller/PartitioningController.scala | 3 ++- .../api/controller/PartitioningControllerImpl.scala | 6 ++++-- .../za/co/absa/atum/server/api/http/Endpoints.scala | 12 ++++++++---- .../CreateCheckpointEndpointIntegrationTests.scala | 9 ++++++--- .../CreatePartitioningEndpointIntegrationTests.scala | 9 ++++++--- 7 files changed, 32 insertions(+), 17 deletions(-) diff --git a/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointController.scala b/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointController.scala index 082d6b3b0..1a4f99a1b 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointController.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointController.scala @@ -24,5 +24,6 @@ import zio.macros.accessible @accessible trait CheckpointController { - def createCheckpoint(checkpointDTO: CheckpointDTO): IO[ErrorResponse, SingleSuccessResponse[CheckpointDTO]] +// def createCheckpoint(checkpointDTO: CheckpointDTO): IO[ErrorResponse, SingleSuccessResponse[CheckpointDTO]] + def createCheckpoint(checkpointDTO: CheckpointDTO): IO[ErrorResponse, CheckpointDTO] } diff --git a/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointControllerImpl.scala b/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointControllerImpl.scala index a03e56ad7..21f392d49 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointControllerImpl.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointControllerImpl.scala @@ -26,13 +26,14 @@ class CheckpointControllerImpl(checkpointService: CheckpointService) extends Che override def createCheckpoint( checkpointDTO: CheckpointDTO - ): IO[ErrorResponse, SingleSuccessResponse[CheckpointDTO]] = { - mapToSingleSuccessResponse( +// ): IO[ErrorResponse, SingleSuccessResponse[CheckpointDTO]] = { + ): IO[ErrorResponse, CheckpointDTO] = { +// mapToSingleSuccessResponse( serviceCallWithStatus[Unit, CheckpointDTO]( checkpointService.saveCheckpoint(checkpointDTO), _ => checkpointDTO ) - ) +// ) } } diff --git a/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningController.scala b/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningController.scala index 62716096b..fa3df43a1 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningController.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningController.scala @@ -26,7 +26,8 @@ import zio.macros.accessible trait PartitioningController { def createPartitioningIfNotExists( partitioningSubmitDTO: PartitioningSubmitDTO - ): IO[ErrorResponse, SingleSuccessResponse[AtumContextDTO]] +// ): IO[ErrorResponse, SingleSuccessResponse[AtumContextDTO]] + ): IO[ErrorResponse, AtumContextDTO] def createOrUpdateAdditionalData( additionalData: AdditionalDataSubmitDTO diff --git a/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningControllerImpl.scala b/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningControllerImpl.scala index 1c078a234..62870f2b9 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningControllerImpl.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningControllerImpl.scala @@ -29,7 +29,8 @@ class PartitioningControllerImpl(partitioningService: PartitioningService) override def createPartitioningIfNotExists( partitioningSubmitDTO: PartitioningSubmitDTO - ): IO[ErrorResponse, SingleSuccessResponse[AtumContextDTO]] = { +// ): IO[ErrorResponse, SingleSuccessResponse[AtumContextDTO]] = { + ): IO[ErrorResponse, AtumContextDTO] = { val atumContextDTOEffect = for { _ <- partitioningService .createPartitioningIfNotExists(partitioningSubmitDTO) @@ -46,7 +47,8 @@ class PartitioningControllerImpl(partitioningService: PartitioningService) } } yield AtumContextDTO(partitioningSubmitDTO.partitioning, measures.toSet, additionalData) - mapToSingleSuccessResponse(atumContextDTOEffect) +// mapToSingleSuccessResponse(atumContextDTOEffect) + atumContextDTOEffect } override def createOrUpdateAdditionalData( diff --git a/server/src/main/scala/za/co/absa/atum/server/api/http/Endpoints.scala b/server/src/main/scala/za/co/absa/atum/server/api/http/Endpoints.scala index 2b31d2a08..629314310 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/http/Endpoints.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/http/Endpoints.scala @@ -30,21 +30,25 @@ import za.co.absa.atum.server.model.SuccessResponse.SingleSuccessResponse trait Endpoints extends BaseEndpoints { protected val createCheckpointEndpoint - : PublicEndpoint[CheckpointDTO, ErrorResponse, SingleSuccessResponse[CheckpointDTO], Any] = { +// : PublicEndpoint[CheckpointDTO, ErrorResponse, SingleSuccessResponse[CheckpointDTO], Any] = { + : PublicEndpoint[CheckpointDTO, ErrorResponse, CheckpointDTO, Any] = { apiV1.post .in(CreateCheckpoint) .in(jsonBody[CheckpointDTO]) .out(statusCode(StatusCode.Created)) - .out(jsonBody[SingleSuccessResponse[CheckpointDTO]]) +// .out(jsonBody[SingleSuccessResponse[CheckpointDTO]]) + .out(jsonBody[CheckpointDTO]) } protected val createPartitioningEndpoint - : PublicEndpoint[PartitioningSubmitDTO, ErrorResponse, SingleSuccessResponse[AtumContextDTO], Any] = { +// : PublicEndpoint[PartitioningSubmitDTO, ErrorResponse, SingleSuccessResponse[AtumContextDTO], Any] = { + : PublicEndpoint[PartitioningSubmitDTO, ErrorResponse, AtumContextDTO, Any] = { apiV1.post .in(CreatePartitioning) .in(jsonBody[PartitioningSubmitDTO]) .out(statusCode(StatusCode.Ok)) - .out(jsonBody[SingleSuccessResponse[AtumContextDTO]]) +// .out(jsonBody[SingleSuccessResponse[AtumContextDTO]]) + .out(jsonBody[AtumContextDTO]) } protected val createOrUpdateAdditionalDataEndpoint diff --git a/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointIntegrationTests.scala b/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointIntegrationTests.scala index c24e646cf..3af16788a 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointIntegrationTests.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointIntegrationTests.scala @@ -38,7 +38,8 @@ object CreateCheckpointEndpointIntegrationTests extends ZIOSpecDefault with Endp private val checkpointControllerMock = mock(classOf[CheckpointController]) when(checkpointControllerMock.createCheckpoint(checkpointDTO1)) - .thenReturn(ZIO.succeed(SingleSuccessResponse(checkpointDTO1))) +// .thenReturn(ZIO.succeed(SingleSuccessResponse(checkpointDTO1))) + .thenReturn(ZIO.succeed(checkpointDTO1)) when(checkpointControllerMock.createCheckpoint(checkpointDTO2)) .thenReturn(ZIO.fail(GeneralErrorResponse("error"))) when(checkpointControllerMock.createCheckpoint(checkpointDTO3)) @@ -57,7 +58,8 @@ object CreateCheckpointEndpointIntegrationTests extends ZIOSpecDefault with Endp val request = basicRequest .post(uri"https://test.com/api/v1/createCheckpoint") - .response(asJson[SingleSuccessResponse[CheckpointDTO]]) +// .response(asJson[SingleSuccessResponse[CheckpointDTO]]) + .response(asJson[CheckpointDTO]) suite("CreateCheckpointEndpointSuite")( test("Returns expected CheckpointDTO") { @@ -68,7 +70,8 @@ object CreateCheckpointEndpointIntegrationTests extends ZIOSpecDefault with Endp val body = response.map(_.body) val statusCode = response.map(_.code) - assertZIO(body <&> statusCode)(equalTo(Right(SingleSuccessResponse(checkpointDTO1)), StatusCode.Created)) +// assertZIO(body <&> statusCode)(equalTo(Right(SingleSuccessResponse(checkpointDTO1)), StatusCode.Created)) + assertZIO(body <&> statusCode)(equalTo(Right(checkpointDTO1), StatusCode.Created)) }, test("Returns expected BadRequest") { val response = request diff --git a/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointIntegrationTests.scala b/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointIntegrationTests.scala index 496156985..7428a4baa 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointIntegrationTests.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointIntegrationTests.scala @@ -38,7 +38,8 @@ object CreatePartitioningEndpointIntegrationTests extends ZIOSpecDefault with En private val createPartitioningEndpointMock = mock(classOf[PartitioningController]) when(createPartitioningEndpointMock.createPartitioningIfNotExists(partitioningSubmitDTO1)) - .thenReturn(ZIO.succeed(SingleSuccessResponse(createAtumContextDTO(partitioningSubmitDTO1)))) +// .thenReturn(ZIO.succeed(SingleSuccessResponse(createAtumContextDTO(partitioningSubmitDTO1)))) + .thenReturn(ZIO.succeed(createAtumContextDTO(partitioningSubmitDTO1))) when(createPartitioningEndpointMock.createPartitioningIfNotExists(partitioningSubmitDTO2)) .thenReturn(ZIO.fail(GeneralErrorResponse("error"))) when(createPartitioningEndpointMock.createPartitioningIfNotExists(partitioningSubmitDTO3)) @@ -57,7 +58,8 @@ object CreatePartitioningEndpointIntegrationTests extends ZIOSpecDefault with En val request = basicRequest .post(uri"https://test.com/api/v1/createPartitioning") - .response(asJson[SingleSuccessResponse[AtumContextDTO]]) +// .response(asJson[SingleSuccessResponse[AtumContextDTO]]) + .response(asJson[AtumContextDTO]) suite("CreatePartitioningEndpointSuite")( test("Returns expected AtumContextDTO") { @@ -69,7 +71,8 @@ object CreatePartitioningEndpointIntegrationTests extends ZIOSpecDefault with En val statusCode = response.map(_.code) assertZIO(body <&> statusCode)( - equalTo(Right(SingleSuccessResponse(createAtumContextDTO(partitioningSubmitDTO1))), StatusCode.Ok) +// equalTo(Right(SingleSuccessResponse(createAtumContextDTO(partitioningSubmitDTO1))), StatusCode.Ok) + equalTo(Right(createAtumContextDTO(partitioningSubmitDTO1)), StatusCode.Ok) ) }, test("Returns expected BadRequest") { From 37539d80d2e22ce4c0f53d597f4e6147a0ec4840 Mon Sep 17 00:00:00 2001 From: Pavel Salamon Date: Mon, 27 May 2024 13:26:33 +0200 Subject: [PATCH 12/25] v2 base endpoint --- .../src/main/scala/za/co/absa/atum/server/Constants.scala | 1 + .../za/co/absa/atum/server/api/http/BaseEndpoints.scala | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/server/src/main/scala/za/co/absa/atum/server/Constants.scala b/server/src/main/scala/za/co/absa/atum/server/Constants.scala index d6f7410e6..1e1736734 100644 --- a/server/src/main/scala/za/co/absa/atum/server/Constants.scala +++ b/server/src/main/scala/za/co/absa/atum/server/Constants.scala @@ -22,6 +22,7 @@ object Constants { final val Api = "api" final val V1 = "v1" + final val V2 = "v2" final val CreatePartitioning = "createPartitioning" final val CreateOrUpdateAdditionalData = "createOrUpdateAdditionalData" diff --git a/server/src/main/scala/za/co/absa/atum/server/api/http/BaseEndpoints.scala b/server/src/main/scala/za/co/absa/atum/server/api/http/BaseEndpoints.scala index 01ed5ff85..1167711f1 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/http/BaseEndpoints.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/http/BaseEndpoints.scala @@ -21,7 +21,7 @@ import sttp.tapir.generic.auto.schemaForCaseClass import sttp.tapir.json.play.jsonBody import sttp.tapir.ztapir._ import sttp.tapir.{EndpointOutput, PublicEndpoint} -import za.co.absa.atum.server.Constants.Endpoints.{Api, V1} +import za.co.absa.atum.server.Constants.Endpoints._ import za.co.absa.atum.server.model.ErrorResponse._ trait BaseEndpoints { @@ -61,4 +61,8 @@ trait BaseEndpoints { baseEndpoint.in(Api / V1) } + protected val apiV2: PublicEndpoint[Unit, ErrorResponse, Unit, Any] = { + baseEndpoint.in(Api / V2) + } + } From 017aa0f59e0d5f717e8c4af23d19668641ab2ea6 Mon Sep 17 00:00:00 2001 From: Pavel Salamon Date: Mon, 27 May 2024 13:41:19 +0200 Subject: [PATCH 13/25] v1 and v2 --- .../agent/dispatcher/HttpDispatcher.scala | 9 +++--- .../api/controller/CheckpointController.scala | 4 +-- .../controller/CheckpointControllerImpl.scala | 19 +++++++------ .../controller/PartitioningController.scala | 7 +++-- .../PartitioningControllerImpl.scala | 10 +++++-- .../absa/atum/server/api/http/Endpoints.scala | 28 +++++++++++++++---- .../co/absa/atum/server/api/http/Routes.scala | 10 ++++--- ...CheckpointControllerIntegrationTests.scala | 6 ++-- ...rtitioningControllerIntegrationTests.scala | 4 +-- ...teCheckpointEndpointIntegrationTests.scala | 17 +++++------ ...PartitioningEndpointIntegrationTests.scala | 17 +++++------ 11 files changed, 77 insertions(+), 54 deletions(-) diff --git a/agent/src/main/scala/za/co/absa/atum/agent/dispatcher/HttpDispatcher.scala b/agent/src/main/scala/za/co/absa/atum/agent/dispatcher/HttpDispatcher.scala index 13548a18c..6e7fdeb31 100644 --- a/agent/src/main/scala/za/co/absa/atum/agent/dispatcher/HttpDispatcher.scala +++ b/agent/src/main/scala/za/co/absa/atum/agent/dispatcher/HttpDispatcher.scala @@ -29,10 +29,11 @@ class HttpDispatcher(config: Config) extends Dispatcher(config: Config) with Log val serverUrl: String = config.getString(UrlKey) - private val currentApiVersion = "/api/v1" - private val createPartitioningEndpoint = Uri.unsafeParse(s"$serverUrl$currentApiVersion/createPartitioning") - private val createCheckpointEndpoint = Uri.unsafeParse(s"$serverUrl$currentApiVersion/createCheckpoint") - private val createAdditionalDataEndpoint = Uri.unsafeParse(s"$serverUrl$currentApiVersion/writeAdditionalData") + private val apiV1 = "/api/v1" + private val apiV2 = "/api/v1" + private val createPartitioningEndpoint = Uri.unsafeParse(s"$serverUrl$apiV1/createPartitioning") + private val createCheckpointEndpoint = Uri.unsafeParse(s"$serverUrl$apiV1/createCheckpoint") + private val createAdditionalDataEndpoint = Uri.unsafeParse(s"$serverUrl$apiV2/writeAdditionalData") private val commonAtumRequest = basicRequest .header("Content-Type", "application/json") diff --git a/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointController.scala b/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointController.scala index 1a4f99a1b..8b6121a05 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointController.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointController.scala @@ -24,6 +24,6 @@ import zio.macros.accessible @accessible trait CheckpointController { -// def createCheckpoint(checkpointDTO: CheckpointDTO): IO[ErrorResponse, SingleSuccessResponse[CheckpointDTO]] - def createCheckpoint(checkpointDTO: CheckpointDTO): IO[ErrorResponse, CheckpointDTO] + def createCheckpointV2(checkpointDTO: CheckpointDTO): IO[ErrorResponse, SingleSuccessResponse[CheckpointDTO]] + def createCheckpointV1(checkpointDTO: CheckpointDTO): IO[ErrorResponse, CheckpointDTO] } diff --git a/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointControllerImpl.scala b/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointControllerImpl.scala index 21f392d49..69a140d55 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointControllerImpl.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointControllerImpl.scala @@ -24,16 +24,19 @@ import zio._ class CheckpointControllerImpl(checkpointService: CheckpointService) extends CheckpointController with BaseController { - override def createCheckpoint( + override def createCheckpointV1( checkpointDTO: CheckpointDTO -// ): IO[ErrorResponse, SingleSuccessResponse[CheckpointDTO]] = { ): IO[ErrorResponse, CheckpointDTO] = { -// mapToSingleSuccessResponse( - serviceCallWithStatus[Unit, CheckpointDTO]( - checkpointService.saveCheckpoint(checkpointDTO), - _ => checkpointDTO - ) -// ) + serviceCallWithStatus[Unit, CheckpointDTO]( + checkpointService.saveCheckpoint(checkpointDTO), + _ => checkpointDTO + ) + } + + override def createCheckpointV2( + checkpointDTO: CheckpointDTO + ): IO[ErrorResponse, SingleSuccessResponse[CheckpointDTO]] = { + mapToSingleSuccessResponse(createCheckpointV1(checkpointDTO)) } } diff --git a/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningController.scala b/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningController.scala index fa3df43a1..5f266afc9 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningController.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningController.scala @@ -24,11 +24,14 @@ import zio.macros.accessible @accessible trait PartitioningController { - def createPartitioningIfNotExists( + def createPartitioningIfNotExistsV1( partitioningSubmitDTO: PartitioningSubmitDTO -// ): IO[ErrorResponse, SingleSuccessResponse[AtumContextDTO]] ): IO[ErrorResponse, AtumContextDTO] + def createPartitioningIfNotExistsV2( + partitioningSubmitDTO: PartitioningSubmitDTO + ): IO[ErrorResponse, SingleSuccessResponse[AtumContextDTO]] + def createOrUpdateAdditionalData( additionalData: AdditionalDataSubmitDTO ): IO[ErrorResponse, SingleSuccessResponse[AdditionalDataSubmitDTO]] diff --git a/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningControllerImpl.scala b/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningControllerImpl.scala index 62870f2b9..baa0ac5fa 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningControllerImpl.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningControllerImpl.scala @@ -27,9 +27,8 @@ class PartitioningControllerImpl(partitioningService: PartitioningService) extends PartitioningController with BaseController { - override def createPartitioningIfNotExists( + override def createPartitioningIfNotExistsV1( partitioningSubmitDTO: PartitioningSubmitDTO -// ): IO[ErrorResponse, SingleSuccessResponse[AtumContextDTO]] = { ): IO[ErrorResponse, AtumContextDTO] = { val atumContextDTOEffect = for { _ <- partitioningService @@ -47,10 +46,15 @@ class PartitioningControllerImpl(partitioningService: PartitioningService) } } yield AtumContextDTO(partitioningSubmitDTO.partitioning, measures.toSet, additionalData) -// mapToSingleSuccessResponse(atumContextDTOEffect) atumContextDTOEffect } + override def createPartitioningIfNotExistsV2( + partitioningSubmitDTO: PartitioningSubmitDTO + ): IO[ErrorResponse, SingleSuccessResponse[AtumContextDTO]] = { + mapToSingleSuccessResponse(createPartitioningIfNotExistsV1(partitioningSubmitDTO)) + } + override def createOrUpdateAdditionalData( additionalData: AdditionalDataSubmitDTO ): IO[ErrorResponse, SingleSuccessResponse[AdditionalDataSubmitDTO]] = { diff --git a/server/src/main/scala/za/co/absa/atum/server/api/http/Endpoints.scala b/server/src/main/scala/za/co/absa/atum/server/api/http/Endpoints.scala index 629314310..fc0bc0d8f 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/http/Endpoints.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/http/Endpoints.scala @@ -29,7 +29,7 @@ import za.co.absa.atum.server.model.SuccessResponse.SingleSuccessResponse trait Endpoints extends BaseEndpoints { - protected val createCheckpointEndpoint + protected val createCheckpointEndpointV1 // : PublicEndpoint[CheckpointDTO, ErrorResponse, SingleSuccessResponse[CheckpointDTO], Any] = { : PublicEndpoint[CheckpointDTO, ErrorResponse, CheckpointDTO, Any] = { apiV1.post @@ -40,20 +40,36 @@ trait Endpoints extends BaseEndpoints { .out(jsonBody[CheckpointDTO]) } - protected val createPartitioningEndpoint -// : PublicEndpoint[PartitioningSubmitDTO, ErrorResponse, SingleSuccessResponse[AtumContextDTO], Any] = { + protected val createCheckpointEndpointV2 + : PublicEndpoint[CheckpointDTO, ErrorResponse, SingleSuccessResponse[CheckpointDTO], Any] = { + apiV2.post + .in(CreateCheckpoint) + .in(jsonBody[CheckpointDTO]) + .out(statusCode(StatusCode.Created)) + .out(jsonBody[SingleSuccessResponse[CheckpointDTO]]) + } + + protected val createPartitioningEndpointV1 : PublicEndpoint[PartitioningSubmitDTO, ErrorResponse, AtumContextDTO, Any] = { apiV1.post .in(CreatePartitioning) .in(jsonBody[PartitioningSubmitDTO]) .out(statusCode(StatusCode.Ok)) -// .out(jsonBody[SingleSuccessResponse[AtumContextDTO]]) .out(jsonBody[AtumContextDTO]) } - protected val createOrUpdateAdditionalDataEndpoint + protected val createPartitioningEndpointV2 + : PublicEndpoint[PartitioningSubmitDTO, ErrorResponse, SingleSuccessResponse[AtumContextDTO], Any] = { + apiV2.post + .in(CreatePartitioning) + .in(jsonBody[PartitioningSubmitDTO]) + .out(statusCode(StatusCode.Ok)) + .out(jsonBody[SingleSuccessResponse[AtumContextDTO]]) + } + + protected val createOrUpdateAdditionalDataEndpointV2 : PublicEndpoint[AdditionalDataSubmitDTO, ErrorResponse, SingleSuccessResponse[AdditionalDataSubmitDTO], Any] = { - apiV1.post + apiV2.post .in(CreateOrUpdateAdditionalData) .in(jsonBody[AdditionalDataSubmitDTO]) .out(statusCode(StatusCode.Ok)) diff --git a/server/src/main/scala/za/co/absa/atum/server/api/http/Routes.scala b/server/src/main/scala/za/co/absa/atum/server/api/http/Routes.scala index e030fd041..216598732 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/http/Routes.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/http/Routes.scala @@ -38,9 +38,11 @@ trait Routes extends Endpoints with ServerOptions { if (httpMonitoringConfig.enabled) Some(HttpMetrics.prometheusMetrics.metricsInterceptor()) else None } val endpoints = List( - createServerEndpoint(createCheckpointEndpoint, CheckpointController.createCheckpoint), - createServerEndpoint(createPartitioningEndpoint, PartitioningController.createPartitioningIfNotExists), - createServerEndpoint(createOrUpdateAdditionalDataEndpoint, PartitioningController.createOrUpdateAdditionalData), + createServerEndpoint(createCheckpointEndpointV1, CheckpointController.createCheckpointV1), + createServerEndpoint(createCheckpointEndpointV2, CheckpointController.createCheckpointV2), + createServerEndpoint(createPartitioningEndpointV1, PartitioningController.createPartitioningIfNotExistsV1), + createServerEndpoint(createPartitioningEndpointV2, PartitioningController.createPartitioningIfNotExistsV2), + createServerEndpoint(createOrUpdateAdditionalDataEndpointV2, PartitioningController.createOrUpdateAdditionalData), createServerEndpoint(healthEndpoint, (_: Unit) => ZIO.unit), ) ZHttp4sServerInterpreter[HttpEnv.Env](http4sServerOptions(metricsInterceptorOption)).from(endpoints).toRoutes @@ -50,7 +52,7 @@ trait Routes extends Endpoints with ServerOptions { Http4sServerInterpreter[HttpEnv.F]().toRoutes(HttpMetrics.prometheusMetrics.metricsEndpoint) private def createSwaggerRoutes: HttpRoutes[HttpEnv.F] = { - val endpoints = List(createCheckpointEndpoint, createPartitioningEndpoint, createOrUpdateAdditionalDataEndpoint) + val endpoints = List(createCheckpointEndpointV1, createPartitioningEndpointV1, createOrUpdateAdditionalDataEndpointV2) ZHttp4sServerInterpreter[HttpEnv.Env](http4sServerOptions(None)) .from(SwaggerInterpreter().fromEndpoints[HttpEnv.F](endpoints, SwaggerApiName, SwaggerApiVersion)) .toRoutes diff --git a/server/src/test/scala/za/co/absa/atum/server/api/controller/CheckpointControllerIntegrationTests.scala b/server/src/test/scala/za/co/absa/atum/server/api/controller/CheckpointControllerIntegrationTests.scala index de098d2e6..5a9894dc7 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/controller/CheckpointControllerIntegrationTests.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/controller/CheckpointControllerIntegrationTests.scala @@ -46,14 +46,14 @@ object CheckpointControllerIntegrationTests extends ZIOSpecDefault with TestData suite("CreateCheckpointSuite")( test("Returns expected CheckpointDTO") { for { - result <- CheckpointController.createCheckpoint(checkpointDTO1) + result <- CheckpointController.createCheckpointV1(checkpointDTO1) } yield assertTrue(result == SingleSuccessResponse(checkpointDTO1)) }, test("Returns expected InternalServerErrorResponse") { - assertZIO(CheckpointController.createCheckpoint(checkpointDTO3).exit)(failsWithA[InternalServerErrorResponse]) + assertZIO(CheckpointController.createCheckpointV1(checkpointDTO3).exit)(failsWithA[InternalServerErrorResponse]) }, test("Returns expected GeneralErrorResponse") { - assertZIO(CheckpointController.createCheckpoint(checkpointDTO2).exit)(failsWithA[GeneralErrorResponse]) + assertZIO(CheckpointController.createCheckpointV1(checkpointDTO2).exit)(failsWithA[GeneralErrorResponse]) } ) ).provide( diff --git a/server/src/test/scala/za/co/absa/atum/server/api/controller/PartitioningControllerIntegrationTests.scala b/server/src/test/scala/za/co/absa/atum/server/api/controller/PartitioningControllerIntegrationTests.scala index 76df06bcc..02fa971d1 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/controller/PartitioningControllerIntegrationTests.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/controller/PartitioningControllerIntegrationTests.scala @@ -47,11 +47,11 @@ object PartitioningControllerIntegrationTests extends ZIOSpecDefault with TestDa suite("CreatePartitioningIfNotExistsSuite")( test("Returns expected AtumContextDTO") { for { - result <- PartitioningController.createPartitioningIfNotExists(partitioningSubmitDTO1) + result <- PartitioningController.createPartitioningIfNotExistsV1(partitioningSubmitDTO1) } yield assertTrue(result == SingleSuccessResponse(atumContextDTO1)) }, test("Returns expected InternalServerErrorResponse") { - assertZIO(PartitioningController.createPartitioningIfNotExists(partitioningSubmitDTO2).exit)( + assertZIO(PartitioningController.createPartitioningIfNotExistsV1(partitioningSubmitDTO2).exit)( failsWithA[InternalServerErrorResponse] ) } diff --git a/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointIntegrationTests.scala b/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointIntegrationTests.scala index 3af16788a..5ed5602d6 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointIntegrationTests.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointIntegrationTests.scala @@ -37,18 +37,17 @@ object CreateCheckpointEndpointIntegrationTests extends ZIOSpecDefault with Endp private val checkpointControllerMock = mock(classOf[CheckpointController]) - when(checkpointControllerMock.createCheckpoint(checkpointDTO1)) -// .thenReturn(ZIO.succeed(SingleSuccessResponse(checkpointDTO1))) - .thenReturn(ZIO.succeed(checkpointDTO1)) - when(checkpointControllerMock.createCheckpoint(checkpointDTO2)) + when(checkpointControllerMock.createCheckpointV2(checkpointDTO1)) + .thenReturn(ZIO.succeed(SingleSuccessResponse(checkpointDTO1))) + when(checkpointControllerMock.createCheckpointV2(checkpointDTO2)) .thenReturn(ZIO.fail(GeneralErrorResponse("error"))) - when(checkpointControllerMock.createCheckpoint(checkpointDTO3)) + when(checkpointControllerMock.createCheckpointV2(checkpointDTO3)) .thenReturn(ZIO.fail(InternalServerErrorResponse("error"))) private val checkpointControllerMockLayer = ZLayer.succeed(checkpointControllerMock) private val createCheckpointServerEndpoint = - createCheckpointEndpoint.zServerLogic(CheckpointController.createCheckpoint) + createCheckpointEndpointV2.zServerLogic(CheckpointController.createCheckpointV2) def spec: Spec[TestEnvironment with Scope, Any] = { val backendStub = TapirStubInterpreter(SttpBackendStub.apply(new RIOMonadError[CheckpointController])) @@ -58,8 +57,7 @@ object CreateCheckpointEndpointIntegrationTests extends ZIOSpecDefault with Endp val request = basicRequest .post(uri"https://test.com/api/v1/createCheckpoint") -// .response(asJson[SingleSuccessResponse[CheckpointDTO]]) - .response(asJson[CheckpointDTO]) + .response(asJson[SingleSuccessResponse[CheckpointDTO]]) suite("CreateCheckpointEndpointSuite")( test("Returns expected CheckpointDTO") { @@ -70,8 +68,7 @@ object CreateCheckpointEndpointIntegrationTests extends ZIOSpecDefault with Endp val body = response.map(_.body) val statusCode = response.map(_.code) -// assertZIO(body <&> statusCode)(equalTo(Right(SingleSuccessResponse(checkpointDTO1)), StatusCode.Created)) - assertZIO(body <&> statusCode)(equalTo(Right(checkpointDTO1), StatusCode.Created)) + assertZIO(body <&> statusCode)(equalTo(Right(SingleSuccessResponse(checkpointDTO1)), StatusCode.Created)) }, test("Returns expected BadRequest") { val response = request diff --git a/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointIntegrationTests.scala b/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointIntegrationTests.scala index 7428a4baa..b6704bbed 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointIntegrationTests.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointIntegrationTests.scala @@ -37,18 +37,17 @@ object CreatePartitioningEndpointIntegrationTests extends ZIOSpecDefault with En private val createPartitioningEndpointMock = mock(classOf[PartitioningController]) - when(createPartitioningEndpointMock.createPartitioningIfNotExists(partitioningSubmitDTO1)) -// .thenReturn(ZIO.succeed(SingleSuccessResponse(createAtumContextDTO(partitioningSubmitDTO1)))) - .thenReturn(ZIO.succeed(createAtumContextDTO(partitioningSubmitDTO1))) - when(createPartitioningEndpointMock.createPartitioningIfNotExists(partitioningSubmitDTO2)) + when(createPartitioningEndpointMock.createPartitioningIfNotExistsV2(partitioningSubmitDTO1)) + .thenReturn(ZIO.succeed(SingleSuccessResponse(createAtumContextDTO(partitioningSubmitDTO1)))) + when(createPartitioningEndpointMock.createPartitioningIfNotExistsV1(partitioningSubmitDTO2)) .thenReturn(ZIO.fail(GeneralErrorResponse("error"))) - when(createPartitioningEndpointMock.createPartitioningIfNotExists(partitioningSubmitDTO3)) + when(createPartitioningEndpointMock.createPartitioningIfNotExistsV1(partitioningSubmitDTO3)) .thenReturn(ZIO.fail(InternalServerErrorResponse("error"))) private val createPartitioningEndpointMockLayer = ZLayer.succeed(createPartitioningEndpointMock) private val createPartitioningServerEndpoint = - createPartitioningEndpoint.zServerLogic(PartitioningController.createPartitioningIfNotExists) + createPartitioningEndpointV2.zServerLogic(PartitioningController.createPartitioningIfNotExistsV2) def spec: Spec[TestEnvironment with Scope, Any] = { val backendStub = TapirStubInterpreter(SttpBackendStub.apply(new RIOMonadError[PartitioningController])) @@ -58,8 +57,7 @@ object CreatePartitioningEndpointIntegrationTests extends ZIOSpecDefault with En val request = basicRequest .post(uri"https://test.com/api/v1/createPartitioning") -// .response(asJson[SingleSuccessResponse[AtumContextDTO]]) - .response(asJson[AtumContextDTO]) + .response(asJson[SingleSuccessResponse[AtumContextDTO]]) suite("CreatePartitioningEndpointSuite")( test("Returns expected AtumContextDTO") { @@ -71,8 +69,7 @@ object CreatePartitioningEndpointIntegrationTests extends ZIOSpecDefault with En val statusCode = response.map(_.code) assertZIO(body <&> statusCode)( -// equalTo(Right(SingleSuccessResponse(createAtumContextDTO(partitioningSubmitDTO1))), StatusCode.Ok) - equalTo(Right(createAtumContextDTO(partitioningSubmitDTO1)), StatusCode.Ok) + equalTo(Right(SingleSuccessResponse(createAtumContextDTO(partitioningSubmitDTO1))), StatusCode.Ok) ) }, test("Returns expected BadRequest") { From a77c65e5c9a2af4df3ad1dc9f8fe64bd9a6c2612 Mon Sep 17 00:00:00 2001 From: Pavel Salamon Date: Mon, 27 May 2024 13:41:53 +0200 Subject: [PATCH 14/25] v1 and v2 --- .../scala/za/co/absa/atum/agent/dispatcher/HttpDispatcher.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agent/src/main/scala/za/co/absa/atum/agent/dispatcher/HttpDispatcher.scala b/agent/src/main/scala/za/co/absa/atum/agent/dispatcher/HttpDispatcher.scala index 6e7fdeb31..cc7ea6623 100644 --- a/agent/src/main/scala/za/co/absa/atum/agent/dispatcher/HttpDispatcher.scala +++ b/agent/src/main/scala/za/co/absa/atum/agent/dispatcher/HttpDispatcher.scala @@ -30,7 +30,7 @@ class HttpDispatcher(config: Config) extends Dispatcher(config: Config) with Log val serverUrl: String = config.getString(UrlKey) private val apiV1 = "/api/v1" - private val apiV2 = "/api/v1" + private val apiV2 = "/api/v2" private val createPartitioningEndpoint = Uri.unsafeParse(s"$serverUrl$apiV1/createPartitioning") private val createCheckpointEndpoint = Uri.unsafeParse(s"$serverUrl$apiV1/createCheckpoint") private val createAdditionalDataEndpoint = Uri.unsafeParse(s"$serverUrl$apiV2/writeAdditionalData") From b57121482e714ab2fcd198bd5922fd80e99c0b4f Mon Sep 17 00:00:00 2001 From: Pavel Salamon Date: Mon, 27 May 2024 13:43:27 +0200 Subject: [PATCH 15/25] cleanup --- .../main/scala/za/co/absa/atum/server/api/http/Endpoints.scala | 2 -- 1 file changed, 2 deletions(-) diff --git a/server/src/main/scala/za/co/absa/atum/server/api/http/Endpoints.scala b/server/src/main/scala/za/co/absa/atum/server/api/http/Endpoints.scala index fc0bc0d8f..9cbde8963 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/http/Endpoints.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/http/Endpoints.scala @@ -30,13 +30,11 @@ import za.co.absa.atum.server.model.SuccessResponse.SingleSuccessResponse trait Endpoints extends BaseEndpoints { protected val createCheckpointEndpointV1 -// : PublicEndpoint[CheckpointDTO, ErrorResponse, SingleSuccessResponse[CheckpointDTO], Any] = { : PublicEndpoint[CheckpointDTO, ErrorResponse, CheckpointDTO, Any] = { apiV1.post .in(CreateCheckpoint) .in(jsonBody[CheckpointDTO]) .out(statusCode(StatusCode.Created)) -// .out(jsonBody[SingleSuccessResponse[CheckpointDTO]]) .out(jsonBody[CheckpointDTO]) } From 121e2b3202072e84a34db50726ad892fd3fb2614 Mon Sep 17 00:00:00 2001 From: Pavel Salamon Date: Mon, 27 May 2024 13:45:59 +0200 Subject: [PATCH 16/25] routes --- .../scala/za/co/absa/atum/server/api/http/Routes.scala | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/server/src/main/scala/za/co/absa/atum/server/api/http/Routes.scala b/server/src/main/scala/za/co/absa/atum/server/api/http/Routes.scala index 216598732..9a1b553af 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/http/Routes.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/http/Routes.scala @@ -43,7 +43,7 @@ trait Routes extends Endpoints with ServerOptions { createServerEndpoint(createPartitioningEndpointV1, PartitioningController.createPartitioningIfNotExistsV1), createServerEndpoint(createPartitioningEndpointV2, PartitioningController.createPartitioningIfNotExistsV2), createServerEndpoint(createOrUpdateAdditionalDataEndpointV2, PartitioningController.createOrUpdateAdditionalData), - createServerEndpoint(healthEndpoint, (_: Unit) => ZIO.unit), + createServerEndpoint(healthEndpoint, (_: Unit) => ZIO.unit) ) ZHttp4sServerInterpreter[HttpEnv.Env](http4sServerOptions(metricsInterceptorOption)).from(endpoints).toRoutes } @@ -52,7 +52,13 @@ trait Routes extends Endpoints with ServerOptions { Http4sServerInterpreter[HttpEnv.F]().toRoutes(HttpMetrics.prometheusMetrics.metricsEndpoint) private def createSwaggerRoutes: HttpRoutes[HttpEnv.F] = { - val endpoints = List(createCheckpointEndpointV1, createPartitioningEndpointV1, createOrUpdateAdditionalDataEndpointV2) + val endpoints = List( + createCheckpointEndpointV1, + createCheckpointEndpointV2, + createPartitioningEndpointV1, + createPartitioningEndpointV2, + createOrUpdateAdditionalDataEndpointV2 + ) ZHttp4sServerInterpreter[HttpEnv.Env](http4sServerOptions(None)) .from(SwaggerInterpreter().fromEndpoints[HttpEnv.F](endpoints, SwaggerApiName, SwaggerApiVersion)) .toRoutes From d1bf834b08dde2db1493a55c745e75688dc4619a Mon Sep 17 00:00:00 2001 From: Pavel Salamon Date: Mon, 27 May 2024 15:11:25 +0200 Subject: [PATCH 17/25] requestId as String --- .../za/co/absa/atum/server/api/http/BaseEndpoints.scala | 7 +++---- .../scala/za/co/absa/atum/server/model/ErrorResponse.scala | 6 +++--- .../za/co/absa/atum/server/model/ResponseEnvelope.scala | 4 +--- .../za/co/absa/atum/server/model/SuccessResponse.scala | 6 +++--- .../controller/CheckpointControllerIntegrationTests.scala | 2 +- .../PartitioningControllerIntegrationTests.scala | 2 +- 6 files changed, 12 insertions(+), 15 deletions(-) diff --git a/server/src/main/scala/za/co/absa/atum/server/api/http/BaseEndpoints.scala b/server/src/main/scala/za/co/absa/atum/server/api/http/BaseEndpoints.scala index 1167711f1..30062c6a9 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/http/BaseEndpoints.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/http/BaseEndpoints.scala @@ -17,11 +17,10 @@ package za.co.absa.atum.server.api.http import sttp.model.StatusCode -import sttp.tapir.generic.auto.schemaForCaseClass +import sttp.tapir._ +import sttp.tapir.generic.auto._ import sttp.tapir.json.play.jsonBody -import sttp.tapir.ztapir._ -import sttp.tapir.{EndpointOutput, PublicEndpoint} -import za.co.absa.atum.server.Constants.Endpoints._ +import za.co.absa.atum.server.Constants.Endpoints.{Api, V1, V2} import za.co.absa.atum.server.model.ErrorResponse._ trait BaseEndpoints { diff --git a/server/src/main/scala/za/co/absa/atum/server/model/ErrorResponse.scala b/server/src/main/scala/za/co/absa/atum/server/model/ErrorResponse.scala index 3ce5aabe4..ecdbfc455 100644 --- a/server/src/main/scala/za/co/absa/atum/server/model/ErrorResponse.scala +++ b/server/src/main/scala/za/co/absa/atum/server/model/ErrorResponse.scala @@ -29,19 +29,19 @@ object ErrorResponse { implicit val reads: Reads[ErrorResponse] = Json.reads[ErrorResponse] implicit val writes: Writes[ErrorResponse] = Json.writes[ErrorResponse] - final case class BadRequestResponse(message: String, override val requestId: UUID = UUID.randomUUID()) + final case class BadRequestResponse(message: String, requestId: String = UUID.randomUUID().toString) extends ErrorResponse implicit val readsBadRequestResponse: Reads[BadRequestResponse] = Json.reads[BadRequestResponse] implicit val writesBadRequestResponse: Writes[BadRequestResponse] = Json.writes[BadRequestResponse] - final case class GeneralErrorResponse(message: String, override val requestId: UUID = UUID.randomUUID()) + final case class GeneralErrorResponse(message: String, requestId: String = UUID.randomUUID().toString) extends ErrorResponse implicit val readsGeneralErrorResponse: Reads[GeneralErrorResponse] = Json.reads[GeneralErrorResponse] implicit val writesGeneralErrorResponse: Writes[GeneralErrorResponse] = Json.writes[GeneralErrorResponse] - final case class InternalServerErrorResponse(message: String, override val requestId: UUID = UUID.randomUUID()) + final case class InternalServerErrorResponse(message: String, requestId: String = UUID.randomUUID().toString) extends ErrorResponse implicit val readsInternalServerErrorResponse: Reads[InternalServerErrorResponse] = diff --git a/server/src/main/scala/za/co/absa/atum/server/model/ResponseEnvelope.scala b/server/src/main/scala/za/co/absa/atum/server/model/ResponseEnvelope.scala index 8fb991d7c..bbf38bd73 100644 --- a/server/src/main/scala/za/co/absa/atum/server/model/ResponseEnvelope.scala +++ b/server/src/main/scala/za/co/absa/atum/server/model/ResponseEnvelope.scala @@ -16,8 +16,6 @@ package za.co.absa.atum.server.model -import java.util.UUID - trait ResponseEnvelope { - def requestId: UUID + def requestId: String } diff --git a/server/src/main/scala/za/co/absa/atum/server/model/SuccessResponse.scala b/server/src/main/scala/za/co/absa/atum/server/model/SuccessResponse.scala index 5320a22f8..46c6e0e5d 100644 --- a/server/src/main/scala/za/co/absa/atum/server/model/SuccessResponse.scala +++ b/server/src/main/scala/za/co/absa/atum/server/model/SuccessResponse.scala @@ -22,10 +22,10 @@ object SuccessResponse { sealed trait SuccessResponse extends ResponseEnvelope - case class SingleSuccessResponse[T](data: T, override val requestId: UUID = UUID.randomUUID()) + case class SingleSuccessResponse[T](data: T, requestId: String = UUID.randomUUID().toString) extends SuccessResponse - case class MultiSuccessResponse[T](data: Seq[T], override val requestId: UUID = UUID.randomUUID()) - extends SuccessResponse + case class MultiSuccessResponse[T](data: Seq[T], requestId: String = UUID.randomUUID().toString) + extends SuccessResponse } diff --git a/server/src/test/scala/za/co/absa/atum/server/api/controller/CheckpointControllerIntegrationTests.scala b/server/src/test/scala/za/co/absa/atum/server/api/controller/CheckpointControllerIntegrationTests.scala index 5a9894dc7..5c71eb3e9 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/controller/CheckpointControllerIntegrationTests.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/controller/CheckpointControllerIntegrationTests.scala @@ -47,7 +47,7 @@ object CheckpointControllerIntegrationTests extends ZIOSpecDefault with TestData test("Returns expected CheckpointDTO") { for { result <- CheckpointController.createCheckpointV1(checkpointDTO1) - } yield assertTrue(result == SingleSuccessResponse(checkpointDTO1)) + } yield assertTrue(result == checkpointDTO1) }, test("Returns expected InternalServerErrorResponse") { assertZIO(CheckpointController.createCheckpointV1(checkpointDTO3).exit)(failsWithA[InternalServerErrorResponse]) diff --git a/server/src/test/scala/za/co/absa/atum/server/api/controller/PartitioningControllerIntegrationTests.scala b/server/src/test/scala/za/co/absa/atum/server/api/controller/PartitioningControllerIntegrationTests.scala index 02fa971d1..ed6284296 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/controller/PartitioningControllerIntegrationTests.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/controller/PartitioningControllerIntegrationTests.scala @@ -48,7 +48,7 @@ object PartitioningControllerIntegrationTests extends ZIOSpecDefault with TestDa test("Returns expected AtumContextDTO") { for { result <- PartitioningController.createPartitioningIfNotExistsV1(partitioningSubmitDTO1) - } yield assertTrue(result == SingleSuccessResponse(atumContextDTO1)) + } yield assertTrue(result == atumContextDTO1) }, test("Returns expected InternalServerErrorResponse") { assertZIO(PartitioningController.createPartitioningIfNotExistsV1(partitioningSubmitDTO2).exit)( From 39273a8541f6ef642557f9e20c613960487e26f7 Mon Sep 17 00:00:00 2001 From: Pavel Salamon Date: Mon, 27 May 2024 15:17:08 +0200 Subject: [PATCH 18/25] fix tests --- .../api/http/CreateCheckpointEndpointIntegrationTests.scala | 2 +- .../api/http/CreatePartitioningEndpointIntegrationTests.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointIntegrationTests.scala b/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointIntegrationTests.scala index 5ed5602d6..65cfe763f 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointIntegrationTests.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointIntegrationTests.scala @@ -56,7 +56,7 @@ object CreateCheckpointEndpointIntegrationTests extends ZIOSpecDefault with Endp .backend() val request = basicRequest - .post(uri"https://test.com/api/v1/createCheckpoint") + .post(uri"https://test.com/api/v2/createCheckpoint") .response(asJson[SingleSuccessResponse[CheckpointDTO]]) suite("CreateCheckpointEndpointSuite")( diff --git a/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointIntegrationTests.scala b/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointIntegrationTests.scala index b6704bbed..451dddb50 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointIntegrationTests.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointIntegrationTests.scala @@ -56,7 +56,7 @@ object CreatePartitioningEndpointIntegrationTests extends ZIOSpecDefault with En .backend() val request = basicRequest - .post(uri"https://test.com/api/v1/createPartitioning") + .post(uri"https://test.com/api/v2/createPartitioning") .response(asJson[SingleSuccessResponse[AtumContextDTO]]) suite("CreatePartitioningEndpointSuite")( From da5fb8470a7eb9d2d6b326549eb6fb0200e6de37 Mon Sep 17 00:00:00 2001 From: Pavel Salamon Date: Mon, 27 May 2024 15:30:03 +0200 Subject: [PATCH 19/25] matchType instance for uuid --- .../za/co/absa/atum/server/api/http/BaseEndpoints.scala | 5 +++++ .../scala/za/co/absa/atum/server/model/ErrorResponse.scala | 6 +++--- .../za/co/absa/atum/server/model/ResponseEnvelope.scala | 4 +++- .../za/co/absa/atum/server/model/SuccessResponse.scala | 4 ++-- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/server/src/main/scala/za/co/absa/atum/server/api/http/BaseEndpoints.scala b/server/src/main/scala/za/co/absa/atum/server/api/http/BaseEndpoints.scala index 30062c6a9..4e35b966a 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/http/BaseEndpoints.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/http/BaseEndpoints.scala @@ -20,11 +20,16 @@ import sttp.model.StatusCode import sttp.tapir._ import sttp.tapir.generic.auto._ import sttp.tapir.json.play.jsonBody +import sttp.tapir.typelevel.MatchType import za.co.absa.atum.server.Constants.Endpoints.{Api, V1, V2} import za.co.absa.atum.server.model.ErrorResponse._ +import java.util.UUID + trait BaseEndpoints { + implicit val uuidMatchType: MatchType[UUID] = (a: Any) => a.isInstanceOf[UUID] + private val badRequestOneOfVariant: EndpointOutput.OneOfVariant[BadRequestResponse] = { oneOfVariantFromMatchType( StatusCode.BadRequest, diff --git a/server/src/main/scala/za/co/absa/atum/server/model/ErrorResponse.scala b/server/src/main/scala/za/co/absa/atum/server/model/ErrorResponse.scala index ecdbfc455..174ff2f2a 100644 --- a/server/src/main/scala/za/co/absa/atum/server/model/ErrorResponse.scala +++ b/server/src/main/scala/za/co/absa/atum/server/model/ErrorResponse.scala @@ -29,19 +29,19 @@ object ErrorResponse { implicit val reads: Reads[ErrorResponse] = Json.reads[ErrorResponse] implicit val writes: Writes[ErrorResponse] = Json.writes[ErrorResponse] - final case class BadRequestResponse(message: String, requestId: String = UUID.randomUUID().toString) + final case class BadRequestResponse(message: String, requestId: UUID = UUID.randomUUID()) extends ErrorResponse implicit val readsBadRequestResponse: Reads[BadRequestResponse] = Json.reads[BadRequestResponse] implicit val writesBadRequestResponse: Writes[BadRequestResponse] = Json.writes[BadRequestResponse] - final case class GeneralErrorResponse(message: String, requestId: String = UUID.randomUUID().toString) + final case class GeneralErrorResponse(message: String, requestId: UUID = UUID.randomUUID()) extends ErrorResponse implicit val readsGeneralErrorResponse: Reads[GeneralErrorResponse] = Json.reads[GeneralErrorResponse] implicit val writesGeneralErrorResponse: Writes[GeneralErrorResponse] = Json.writes[GeneralErrorResponse] - final case class InternalServerErrorResponse(message: String, requestId: String = UUID.randomUUID().toString) + final case class InternalServerErrorResponse(message: String, requestId: UUID = UUID.randomUUID()) extends ErrorResponse implicit val readsInternalServerErrorResponse: Reads[InternalServerErrorResponse] = diff --git a/server/src/main/scala/za/co/absa/atum/server/model/ResponseEnvelope.scala b/server/src/main/scala/za/co/absa/atum/server/model/ResponseEnvelope.scala index bbf38bd73..8fb991d7c 100644 --- a/server/src/main/scala/za/co/absa/atum/server/model/ResponseEnvelope.scala +++ b/server/src/main/scala/za/co/absa/atum/server/model/ResponseEnvelope.scala @@ -16,6 +16,8 @@ package za.co.absa.atum.server.model +import java.util.UUID + trait ResponseEnvelope { - def requestId: String + def requestId: UUID } diff --git a/server/src/main/scala/za/co/absa/atum/server/model/SuccessResponse.scala b/server/src/main/scala/za/co/absa/atum/server/model/SuccessResponse.scala index 46c6e0e5d..8ab99255d 100644 --- a/server/src/main/scala/za/co/absa/atum/server/model/SuccessResponse.scala +++ b/server/src/main/scala/za/co/absa/atum/server/model/SuccessResponse.scala @@ -22,10 +22,10 @@ object SuccessResponse { sealed trait SuccessResponse extends ResponseEnvelope - case class SingleSuccessResponse[T](data: T, requestId: String = UUID.randomUUID().toString) + case class SingleSuccessResponse[T](data: T, requestId: UUID = UUID.randomUUID()) extends SuccessResponse - case class MultiSuccessResponse[T](data: Seq[T], requestId: String = UUID.randomUUID().toString) + case class MultiSuccessResponse[T](data: Seq[T], requestId: UUID = UUID.randomUUID()) extends SuccessResponse } From dfc3a4f2b1d9dd31c4613b094f4f6388edeb3a97 Mon Sep 17 00:00:00 2001 From: Pavel Salamon Date: Mon, 27 May 2024 15:43:30 +0200 Subject: [PATCH 20/25] fix tests --- .../api/http/CreatePartitioningEndpointIntegrationTests.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointIntegrationTests.scala b/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointIntegrationTests.scala index 451dddb50..816bddfbc 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointIntegrationTests.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointIntegrationTests.scala @@ -39,9 +39,9 @@ object CreatePartitioningEndpointIntegrationTests extends ZIOSpecDefault with En when(createPartitioningEndpointMock.createPartitioningIfNotExistsV2(partitioningSubmitDTO1)) .thenReturn(ZIO.succeed(SingleSuccessResponse(createAtumContextDTO(partitioningSubmitDTO1)))) - when(createPartitioningEndpointMock.createPartitioningIfNotExistsV1(partitioningSubmitDTO2)) + when(createPartitioningEndpointMock.createPartitioningIfNotExistsV2(partitioningSubmitDTO2)) .thenReturn(ZIO.fail(GeneralErrorResponse("error"))) - when(createPartitioningEndpointMock.createPartitioningIfNotExistsV1(partitioningSubmitDTO3)) + when(createPartitioningEndpointMock.createPartitioningIfNotExistsV2(partitioningSubmitDTO3)) .thenReturn(ZIO.fail(InternalServerErrorResponse("error"))) private val createPartitioningEndpointMockLayer = ZLayer.succeed(createPartitioningEndpointMock) From 71d98d3d02a067ec6b046cde269ea47158146317 Mon Sep 17 00:00:00 2001 From: Pavel Salamon Date: Mon, 27 May 2024 15:54:05 +0200 Subject: [PATCH 21/25] fix tests --- .../test/scala/za/co/absa/atum/server/api/TestData.scala | 2 ++ .../api/http/CreateCheckpointEndpointIntegrationTests.scala | 4 ++-- .../http/CreatePartitioningEndpointIntegrationTests.scala | 6 ++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/server/src/test/scala/za/co/absa/atum/server/api/TestData.scala b/server/src/test/scala/za/co/absa/atum/server/api/TestData.scala index 4e8f84500..1dab29abd 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/TestData.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/TestData.scala @@ -22,6 +22,8 @@ import java.util.UUID trait TestData { + protected val uuid = UUID.randomUUID() + // Partitioning DTO protected val partitioningDTO1: PartitioningDTO = Seq( PartitionDTO("key1", "val1"), diff --git a/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointIntegrationTests.scala b/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointIntegrationTests.scala index 65cfe763f..6568ae944 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointIntegrationTests.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/http/CreateCheckpointEndpointIntegrationTests.scala @@ -38,7 +38,7 @@ object CreateCheckpointEndpointIntegrationTests extends ZIOSpecDefault with Endp private val checkpointControllerMock = mock(classOf[CheckpointController]) when(checkpointControllerMock.createCheckpointV2(checkpointDTO1)) - .thenReturn(ZIO.succeed(SingleSuccessResponse(checkpointDTO1))) + .thenReturn(ZIO.succeed(SingleSuccessResponse(checkpointDTO1, uuid))) when(checkpointControllerMock.createCheckpointV2(checkpointDTO2)) .thenReturn(ZIO.fail(GeneralErrorResponse("error"))) when(checkpointControllerMock.createCheckpointV2(checkpointDTO3)) @@ -68,7 +68,7 @@ object CreateCheckpointEndpointIntegrationTests extends ZIOSpecDefault with Endp val body = response.map(_.body) val statusCode = response.map(_.code) - assertZIO(body <&> statusCode)(equalTo(Right(SingleSuccessResponse(checkpointDTO1)), StatusCode.Created)) + assertZIO(body <&> statusCode)(equalTo(Right(SingleSuccessResponse(checkpointDTO1, uuid)), StatusCode.Created)) }, test("Returns expected BadRequest") { val response = request diff --git a/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointIntegrationTests.scala b/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointIntegrationTests.scala index 816bddfbc..9e4d60484 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointIntegrationTests.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/http/CreatePartitioningEndpointIntegrationTests.scala @@ -33,12 +33,14 @@ import zio._ import zio.test.Assertion.equalTo import zio.test._ +import java.util.UUID + object CreatePartitioningEndpointIntegrationTests extends ZIOSpecDefault with Endpoints with TestData { private val createPartitioningEndpointMock = mock(classOf[PartitioningController]) when(createPartitioningEndpointMock.createPartitioningIfNotExistsV2(partitioningSubmitDTO1)) - .thenReturn(ZIO.succeed(SingleSuccessResponse(createAtumContextDTO(partitioningSubmitDTO1)))) + .thenReturn(ZIO.succeed(SingleSuccessResponse(createAtumContextDTO(partitioningSubmitDTO1), uuid))) when(createPartitioningEndpointMock.createPartitioningIfNotExistsV2(partitioningSubmitDTO2)) .thenReturn(ZIO.fail(GeneralErrorResponse("error"))) when(createPartitioningEndpointMock.createPartitioningIfNotExistsV2(partitioningSubmitDTO3)) @@ -69,7 +71,7 @@ object CreatePartitioningEndpointIntegrationTests extends ZIOSpecDefault with En val statusCode = response.map(_.code) assertZIO(body <&> statusCode)( - equalTo(Right(SingleSuccessResponse(createAtumContextDTO(partitioningSubmitDTO1))), StatusCode.Ok) + equalTo(Right(SingleSuccessResponse(createAtumContextDTO(partitioningSubmitDTO1), uuid)), StatusCode.Ok) ) }, test("Returns expected BadRequest") { From 5fd5f88fb92c1cc8776a0dbfe39c2b51501e2580 Mon Sep 17 00:00:00 2001 From: Pavel Salamon Date: Mon, 27 May 2024 16:36:51 +0200 Subject: [PATCH 22/25] fix tests --- .../atum/server/api/controller/CheckpointController.scala | 7 ++++++- .../PartitioningControllerIntegrationTests.scala | 8 +++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointController.scala b/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointController.scala index 8b6121a05..402b67884 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointController.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/controller/CheckpointController.scala @@ -24,6 +24,11 @@ import zio.macros.accessible @accessible trait CheckpointController { - def createCheckpointV2(checkpointDTO: CheckpointDTO): IO[ErrorResponse, SingleSuccessResponse[CheckpointDTO]] + def createCheckpointV1(checkpointDTO: CheckpointDTO): IO[ErrorResponse, CheckpointDTO] + + def createCheckpointV2( + checkpointDTO: CheckpointDTO + ): IO[ErrorResponse, SingleSuccessResponse[CheckpointDTO]] + } diff --git a/server/src/test/scala/za/co/absa/atum/server/api/controller/PartitioningControllerIntegrationTests.scala b/server/src/test/scala/za/co/absa/atum/server/api/controller/PartitioningControllerIntegrationTests.scala index ed6284296..635b0f126 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/controller/PartitioningControllerIntegrationTests.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/controller/PartitioningControllerIntegrationTests.scala @@ -58,9 +58,11 @@ object PartitioningControllerIntegrationTests extends ZIOSpecDefault with TestDa ), suite("CreateOrUpdateAdditionalDataSuite")( test("Returns expected AdditionalDataSubmitDTO") { - assertZIO(PartitioningController.createOrUpdateAdditionalData(additionalDataSubmitDTO1))( - equalTo(SingleSuccessResponse(additionalDataSubmitDTO1)) - ) + for { + result <- PartitioningController.createOrUpdateAdditionalData(additionalDataSubmitDTO1) + expected = SingleSuccessResponse(additionalDataSubmitDTO1, uuid) + actual = result.copy(requestId = uuid) + } yield assert(actual)(equalTo(expected)) }, test("Returns expected InternalServerErrorResponse") { assertZIO(PartitioningController.createOrUpdateAdditionalData(additionalDataSubmitDTO2).exit)( From 151384964a425d936a67de1a95e62e56586ebe25 Mon Sep 17 00:00:00 2001 From: Pavel Salamon Date: Tue, 28 May 2024 07:52:26 +0200 Subject: [PATCH 23/25] renamed method to createOrUpdateAdditionalDataV2 --- .../atum/server/api/controller/PartitioningController.scala | 2 +- .../server/api/controller/PartitioningControllerImpl.scala | 2 +- .../main/scala/za/co/absa/atum/server/api/http/Routes.scala | 2 +- .../controller/PartitioningControllerIntegrationTests.scala | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningController.scala b/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningController.scala index 5f266afc9..21175b41a 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningController.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningController.scala @@ -32,7 +32,7 @@ trait PartitioningController { partitioningSubmitDTO: PartitioningSubmitDTO ): IO[ErrorResponse, SingleSuccessResponse[AtumContextDTO]] - def createOrUpdateAdditionalData( + def createOrUpdateAdditionalDataV2( additionalData: AdditionalDataSubmitDTO ): IO[ErrorResponse, SingleSuccessResponse[AdditionalDataSubmitDTO]] } diff --git a/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningControllerImpl.scala b/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningControllerImpl.scala index baa0ac5fa..2fb66baed 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningControllerImpl.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningControllerImpl.scala @@ -55,7 +55,7 @@ class PartitioningControllerImpl(partitioningService: PartitioningService) mapToSingleSuccessResponse(createPartitioningIfNotExistsV1(partitioningSubmitDTO)) } - override def createOrUpdateAdditionalData( + override def createOrUpdateAdditionalDataV2( additionalData: AdditionalDataSubmitDTO ): IO[ErrorResponse, SingleSuccessResponse[AdditionalDataSubmitDTO]] = { mapToSingleSuccessResponse( diff --git a/server/src/main/scala/za/co/absa/atum/server/api/http/Routes.scala b/server/src/main/scala/za/co/absa/atum/server/api/http/Routes.scala index 9a1b553af..6b9506172 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/http/Routes.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/http/Routes.scala @@ -42,7 +42,7 @@ trait Routes extends Endpoints with ServerOptions { createServerEndpoint(createCheckpointEndpointV2, CheckpointController.createCheckpointV2), createServerEndpoint(createPartitioningEndpointV1, PartitioningController.createPartitioningIfNotExistsV1), createServerEndpoint(createPartitioningEndpointV2, PartitioningController.createPartitioningIfNotExistsV2), - createServerEndpoint(createOrUpdateAdditionalDataEndpointV2, PartitioningController.createOrUpdateAdditionalData), + createServerEndpoint(createOrUpdateAdditionalDataEndpointV2, PartitioningController.createOrUpdateAdditionalDataV2), createServerEndpoint(healthEndpoint, (_: Unit) => ZIO.unit) ) ZHttp4sServerInterpreter[HttpEnv.Env](http4sServerOptions(metricsInterceptorOption)).from(endpoints).toRoutes diff --git a/server/src/test/scala/za/co/absa/atum/server/api/controller/PartitioningControllerIntegrationTests.scala b/server/src/test/scala/za/co/absa/atum/server/api/controller/PartitioningControllerIntegrationTests.scala index 635b0f126..854b4e351 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/controller/PartitioningControllerIntegrationTests.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/controller/PartitioningControllerIntegrationTests.scala @@ -59,13 +59,13 @@ object PartitioningControllerIntegrationTests extends ZIOSpecDefault with TestDa suite("CreateOrUpdateAdditionalDataSuite")( test("Returns expected AdditionalDataSubmitDTO") { for { - result <- PartitioningController.createOrUpdateAdditionalData(additionalDataSubmitDTO1) + result <- PartitioningController.createOrUpdateAdditionalDataV2(additionalDataSubmitDTO1) expected = SingleSuccessResponse(additionalDataSubmitDTO1, uuid) actual = result.copy(requestId = uuid) } yield assert(actual)(equalTo(expected)) }, test("Returns expected InternalServerErrorResponse") { - assertZIO(PartitioningController.createOrUpdateAdditionalData(additionalDataSubmitDTO2).exit)( + assertZIO(PartitioningController.createOrUpdateAdditionalDataV2(additionalDataSubmitDTO2).exit)( failsWithA[InternalServerErrorResponse] ) } From 0c1f2abdbbfec670c65312c02576b521a975c813 Mon Sep 17 00:00:00 2001 From: Pavel Salamon Date: Thu, 13 Jun 2024 12:21:37 +0200 Subject: [PATCH 24/25] resolve conflicts, add envelope --- .../controller/PartitioningController.scala | 6 +++--- .../PartitioningControllerImpl.scala | 18 +++++++++++------- .../absa/atum/server/api/http/Endpoints.scala | 6 +++--- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningController.scala b/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningController.scala index bd0297e1e..d8fd2669c 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningController.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningController.scala @@ -16,9 +16,9 @@ package za.co.absa.atum.server.api.controller -import za.co.absa.atum.model.dto.{AdditionalDataSubmitDTO, AtumContextDTO, CheckpointDTO, PartitioningSubmitDTO} +import za.co.absa.atum.model.dto.{AdditionalDataSubmitDTO, AtumContextDTO, CheckpointDTO, CheckpointQueryDTO, PartitioningSubmitDTO} import za.co.absa.atum.server.model.ErrorResponse.ErrorResponse -import za.co.absa.atum.server.model.SuccessResponse.SingleSuccessResponse +import za.co.absa.atum.server.model.SuccessResponse.{MultiSuccessResponse, SingleSuccessResponse} import zio.IO import zio.macros.accessible @@ -36,5 +36,5 @@ trait PartitioningController { additionalData: AdditionalDataSubmitDTO ): IO[ErrorResponse, SingleSuccessResponse[AdditionalDataSubmitDTO]] - def getPartitioningCheckpoints(checkpointQueryDTO: CheckpointQueryDTO): IO[ErrorResponse, Seq[CheckpointDTO]] + def getPartitioningCheckpoints(checkpointQueryDTO: CheckpointQueryDTO): IO[ErrorResponse, MultiSuccessResponse[CheckpointDTO]] } diff --git a/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningControllerImpl.scala b/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningControllerImpl.scala index 92585847e..e9bbcef18 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningControllerImpl.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/controller/PartitioningControllerImpl.scala @@ -20,11 +20,12 @@ import za.co.absa.atum.model.dto._ import za.co.absa.atum.server.api.exception.ServiceError import za.co.absa.atum.server.api.service.PartitioningService import za.co.absa.atum.server.model.ErrorResponse.{ErrorResponse, InternalServerErrorResponse} -import za.co.absa.atum.server.model.SuccessResponse.SingleSuccessResponse +import za.co.absa.atum.server.model.SuccessResponse.{MultiSuccessResponse, SingleSuccessResponse} import zio._ class PartitioningControllerImpl(partitioningService: PartitioningService) - extends PartitioningController with BaseController { + extends PartitioningController + with BaseController { override def createPartitioningIfNotExistsV1( partitioningSubmitDTO: PartitioningSubmitDTO @@ -65,11 +66,14 @@ class PartitioningControllerImpl(partitioningService: PartitioningService) ) } - override def getPartitioningCheckpoints(checkpointQueryDTO: CheckpointQueryDTO): - IO[ErrorResponse, Seq[CheckpointDTO]] = { - serviceCall[Seq[CheckpointDTO], Seq[CheckpointDTO]]( - partitioningService.getPartitioningCheckpoints(checkpointQueryDTO), - checkpoints => checkpoints + override def getPartitioningCheckpoints( + checkpointQueryDTO: CheckpointQueryDTO + ): IO[ErrorResponse, MultiSuccessResponse[CheckpointDTO]] = { + mapToMultiSuccessResponse( + serviceCall[Seq[CheckpointDTO], Seq[CheckpointDTO]]( + partitioningService.getPartitioningCheckpoints(checkpointQueryDTO), + checkpoints => checkpoints + ) ) } diff --git a/server/src/main/scala/za/co/absa/atum/server/api/http/Endpoints.scala b/server/src/main/scala/za/co/absa/atum/server/api/http/Endpoints.scala index 6d3743436..9adbcd84b 100644 --- a/server/src/main/scala/za/co/absa/atum/server/api/http/Endpoints.scala +++ b/server/src/main/scala/za/co/absa/atum/server/api/http/Endpoints.scala @@ -25,7 +25,7 @@ import za.co.absa.atum.model.dto._ import za.co.absa.atum.server.Constants.Endpoints._ import za.co.absa.atum.server.model.ErrorResponse.ErrorResponse import za.co.absa.atum.server.model.PlayJsonImplicits._ -import za.co.absa.atum.server.model.SuccessResponse.SingleSuccessResponse +import za.co.absa.atum.server.model.SuccessResponse.{MultiSuccessResponse, SingleSuccessResponse} trait Endpoints extends BaseEndpoints { @@ -75,12 +75,12 @@ trait Endpoints extends BaseEndpoints { } protected val getPartitioningCheckpointsEndpointV2 - : PublicEndpoint[CheckpointQueryDTO, ErrorResponse, Seq[CheckpointDTO], Any] = { + : PublicEndpoint[CheckpointQueryDTO, ErrorResponse, MultiSuccessResponse[CheckpointDTO], Any] = { apiV2.get .in(GetPartitioningCheckpoints) .in(jsonBody[CheckpointQueryDTO]) .out(statusCode(StatusCode.Ok)) - .out(jsonBody[Seq[CheckpointDTO]]) + .out(jsonBody[MultiSuccessResponse[CheckpointDTO]]) } protected val zioMetricsEndpoint: PublicEndpoint[Unit, Unit, String, Any] = { From 182556f4745321a3505eaa37af49df092c388585 Mon Sep 17 00:00:00 2001 From: Pavel Salamon Date: Thu, 13 Jun 2024 12:32:19 +0200 Subject: [PATCH 25/25] fix of tests --- .../api/controller/PartitioningControllerUnitTests.scala | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/server/src/test/scala/za/co/absa/atum/server/api/controller/PartitioningControllerUnitTests.scala b/server/src/test/scala/za/co/absa/atum/server/api/controller/PartitioningControllerUnitTests.scala index bb68fda81..ebc7b8d61 100644 --- a/server/src/test/scala/za/co/absa/atum/server/api/controller/PartitioningControllerUnitTests.scala +++ b/server/src/test/scala/za/co/absa/atum/server/api/controller/PartitioningControllerUnitTests.scala @@ -17,11 +17,12 @@ package za.co.absa.atum.server.api.controller import org.mockito.Mockito.{mock, when} +import za.co.absa.atum.model.dto.CheckpointDTO import za.co.absa.atum.server.api.TestData import za.co.absa.atum.server.api.exception.ServiceError import za.co.absa.atum.server.api.service.PartitioningService import za.co.absa.atum.server.model.ErrorResponse.InternalServerErrorResponse -import za.co.absa.atum.server.model.SuccessResponse.SingleSuccessResponse +import za.co.absa.atum.server.model.SuccessResponse.{MultiSuccessResponse, SingleSuccessResponse} import zio._ import zio.test.Assertion.{equalTo, failsWithA} import zio.test._ @@ -87,12 +88,12 @@ object PartitioningControllerUnitTests extends ZIOSpecDefault with TestData { test("Returns expected Seq[MeasureDTO]") { for { result <- PartitioningController.getPartitioningCheckpoints(checkpointQueryDTO1) - } yield assertTrue(result == Seq(checkpointDTO1, checkpointDTO2)) + } yield assertTrue(result.data == Seq(checkpointDTO1, checkpointDTO2)) }, test("Returns expected empty sequence") { for { result <- PartitioningController.getPartitioningCheckpoints(checkpointQueryDTO2) - } yield assertTrue(result == Seq.empty) + } yield assertTrue(result.data == Seq.empty[CheckpointDTO]) }, test("Returns expected InternalServerErrorResponse") { assertZIO(PartitioningController.getPartitioningCheckpoints(checkpointQueryDTO3).exit)(