From 2167d02a3b0deecc98efeab7425fd4931433d224 Mon Sep 17 00:00:00 2001 From: Nariman Abdullin Date: Wed, 3 Aug 2022 12:11:24 +0300 Subject: [PATCH] review note #5 --- db/test-data/git-insert.xml | 2 +- db/test-data/sqlRequests/organization.csv | 3 ++- .../controllers/ExecutionController.kt | 2 +- .../controllers/TestSuitesController.kt | 4 ++-- .../controllers/TestSuitesSourceController.kt | 11 ++++++++-- .../backend/repository/TestSuiteRepository.kt | 8 ------- .../save/backend/service/GitService.kt | 11 +++++++++- .../save/backend/service/TestSuitesService.kt | 21 ++++++++++++++++--- .../service/TestSuitesSourceService.kt | 2 +- .../save/backend/utils/ReactorUtils.kt | 13 ++++++++++++ 10 files changed, 57 insertions(+), 20 deletions(-) diff --git a/db/test-data/git-insert.xml b/db/test-data/git-insert.xml index cea6fc370a..b7c3a101c1 100644 --- a/db/test-data/git-insert.xml +++ b/db/test-data/git-insert.xml @@ -27,7 +27,7 @@ - + \ No newline at end of file diff --git a/db/test-data/sqlRequests/organization.csv b/db/test-data/sqlRequests/organization.csv index ba48e46f15..bf92d68bd8 100644 --- a/db/test-data/sqlRequests/organization.csv +++ b/db/test-data/sqlRequests/organization.csv @@ -1,3 +1,4 @@ id;name;owner_id;date_created;can_create_contests 1;"Huawei";1;"2021-01-01 00:00:00";true -2;"Example.com";1;"2021-01-01 00:00:00";false \ No newline at end of file +2;"Example.com";1;"2021-01-01 00:00:00";false +3;"CQFN.org";1;"2022-01-01 00:00:00";false \ No newline at end of file diff --git a/save-backend/src/main/kotlin/com/saveourtool/save/backend/controllers/ExecutionController.kt b/save-backend/src/main/kotlin/com/saveourtool/save/backend/controllers/ExecutionController.kt index 6dcfc460b0..9d3da1998e 100644 --- a/save-backend/src/main/kotlin/com/saveourtool/save/backend/controllers/ExecutionController.kt +++ b/save-backend/src/main/kotlin/com/saveourtool/save/backend/controllers/ExecutionController.kt @@ -298,9 +298,9 @@ class ExecutionController(private val executionService: ExecutionService, )) { throw ResponseStatusException(HttpStatus.FORBIDDEN) } - val executionType = execution.type val git = gitService.getByOrganizationAndUrl(execution.project.organization, execution.getTestSuiteRepoUrl()) .toDto() + val executionType = execution.type val testRootPath = if (executionType == ExecutionType.GIT) { execution.getTestRootPathByTestSuites() .distinct() diff --git a/save-backend/src/main/kotlin/com/saveourtool/save/backend/controllers/TestSuitesController.kt b/save-backend/src/main/kotlin/com/saveourtool/save/backend/controllers/TestSuitesController.kt index 84fb8679a0..d97f678c42 100644 --- a/save-backend/src/main/kotlin/com/saveourtool/save/backend/controllers/TestSuitesController.kt +++ b/save-backend/src/main/kotlin/com/saveourtool/save/backend/controllers/TestSuitesController.kt @@ -43,8 +43,8 @@ class TestSuitesController( * @return response with list of test suite dtos */ @GetMapping(path = ["/api/$v1/allStandardTestSuites", "/internal/allStandardTestSuites"]) - fun getAllStandardTestSuites(): ResponseListTestSuites = - ResponseEntity.status(HttpStatus.OK).body(testSuitesService.getStandardTestSuites()) + fun getAllStandardTestSuites(): Mono = + testSuitesService.getStandardTestSuites().map { ResponseEntity.status(HttpStatus.OK).body(it) } /** * @param id id of the test suite diff --git a/save-backend/src/main/kotlin/com/saveourtool/save/backend/controllers/TestSuitesSourceController.kt b/save-backend/src/main/kotlin/com/saveourtool/save/backend/controllers/TestSuitesSourceController.kt index fe0833869b..a6c2cfde92 100644 --- a/save-backend/src/main/kotlin/com/saveourtool/save/backend/controllers/TestSuitesSourceController.kt +++ b/save-backend/src/main/kotlin/com/saveourtool/save/backend/controllers/TestSuitesSourceController.kt @@ -28,6 +28,8 @@ import org.springframework.web.bind.annotation.* import reactor.core.publisher.Mono import reactor.kotlin.core.publisher.toFlux import reactor.kotlin.core.publisher.toMono +import reactor.kotlin.core.util.function.component1 +import reactor.kotlin.core.util.function.component2 typealias TestSuiteList = List @@ -307,14 +309,19 @@ class TestSuitesSourceController( ) @ApiResponse(responseCode = "200", description = "Successfully get or create test suites source with requested values.") @ApiResponse(responseCode = "409", description = "Organization was not found by provided name.") + @ApiResponse(responseCode = "409", description = "Git credentials was not found by provided url.") fun getOrCreate( @PathVariable organizationName: String, @RequestParam gitUrl: String, @RequestParam testRootPath: String, @RequestParam branch: String, ): Mono = getOrganization(organizationName) - .map { organization -> - organization to gitService.getByOrganizationAndUrl(organization, gitUrl) + .zipWhen { organization -> + gitService.findByOrganizationAndUrl(organization, gitUrl) + .toMono() + .switchIfEmptyToResponseException(HttpStatus.CONFLICT) { + "There is no git credential with url $gitUrl in $organizationName" + } } .map { (organization, git) -> testSuitesSourceService.getOrCreate(organization, git, testRootPath, branch) diff --git a/save-backend/src/main/kotlin/com/saveourtool/save/backend/repository/TestSuiteRepository.kt b/save-backend/src/main/kotlin/com/saveourtool/save/backend/repository/TestSuiteRepository.kt index e4b9b216a3..d98de63603 100644 --- a/save-backend/src/main/kotlin/com/saveourtool/save/backend/repository/TestSuiteRepository.kt +++ b/save-backend/src/main/kotlin/com/saveourtool/save/backend/repository/TestSuiteRepository.kt @@ -31,12 +31,4 @@ interface TestSuiteRepository : BaseEntityRepository, QueryByExampleE source: TestSuitesSource, version: String ): List - - /** - * @param source source of the test suite - * @return matched test suites - */ - fun findAllBySource( - source: TestSuitesSource, - ): List } diff --git a/save-backend/src/main/kotlin/com/saveourtool/save/backend/service/GitService.kt b/save-backend/src/main/kotlin/com/saveourtool/save/backend/service/GitService.kt index 4b718aeb8b..503569574b 100644 --- a/save-backend/src/main/kotlin/com/saveourtool/save/backend/service/GitService.kt +++ b/save-backend/src/main/kotlin/com/saveourtool/save/backend/service/GitService.kt @@ -18,12 +18,21 @@ class GitService(private val gitRepository: GitRepository) { */ fun getAllByOrganization(organization: Organization): List = gitRepository.findAllByOrganizationId(organization.requiredId()) + /** + * @param organization + * @param url + * @return list of gits by organization if exists or null + */ + fun findByOrganizationAndUrl(organization: Organization, url: String): Git? = gitRepository.findByOrganizationAndUrl(organization, url) + + /** * @param organization * @param url * @return list of gits by organization if exists + * @throws NoSuchElementException */ - fun getByOrganizationAndUrl(organization: Organization, url: String): Git = gitRepository.findByOrganizationAndUrl(organization, url) + fun getByOrganizationAndUrl(organization: Organization, url: String): Git = findByOrganizationAndUrl(organization, url) ?: throw NoSuchElementException("There is no git credential with url $url in ${organization.name}") /** diff --git a/save-backend/src/main/kotlin/com/saveourtool/save/backend/service/TestSuitesService.kt b/save-backend/src/main/kotlin/com/saveourtool/save/backend/service/TestSuitesService.kt index 47118210e7..9ee0a32b28 100644 --- a/save-backend/src/main/kotlin/com/saveourtool/save/backend/service/TestSuitesService.kt +++ b/save-backend/src/main/kotlin/com/saveourtool/save/backend/service/TestSuitesService.kt @@ -3,6 +3,8 @@ package com.saveourtool.save.backend.service import com.saveourtool.save.backend.repository.TestExecutionRepository import com.saveourtool.save.backend.repository.TestRepository import com.saveourtool.save.backend.repository.TestSuiteRepository +import com.saveourtool.save.backend.storage.TestSuitesSourceSnapshotStorage +import com.saveourtool.save.backend.utils.blockingToFlux import com.saveourtool.save.entities.TestSuite import com.saveourtool.save.entities.TestSuitesSource import com.saveourtool.save.testsuite.TestSuiteDto @@ -13,8 +15,12 @@ import org.springframework.data.domain.Example import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.web.server.ResponseStatusException +import reactor.core.publisher.Mono +import reactor.kotlin.extra.math.max import java.time.LocalDateTime +typealias TestSuiteDtoList = List + /** * Service for test suites */ @@ -24,6 +30,7 @@ class TestSuitesService( private val testRepository: TestRepository, private val testExecutionRepository: TestExecutionRepository, private val testSuitesSourceService: TestSuitesSourceService, + private val testSuitesSourceSnapshotStorage: TestSuitesSourceSnapshotStorage, ) { /** * Save new test suites to DB @@ -76,9 +83,17 @@ class TestSuitesService( /** * @return all standard test suites */ - fun getStandardTestSuites() = testSuitesSourceService.getStandardTestSuitesSources() - .flatMap { testSuitesSource -> testSuiteRepository.findAllBySource(testSuitesSource) } - .map { it.toDto() } + fun getStandardTestSuites(): Mono = blockingToFlux { testSuitesSourceService.getStandardTestSuitesSources() } + .flatMap { testSuitesSource -> + testSuitesSourceSnapshotStorage.list(testSuitesSource.organization.name, testSuitesSource.name) + .max { max, next -> max.creationTimeInMills.compareTo(next.creationTimeInMills) } + .map { testSuitesSource to it.version } + } + .flatMap { (testSuitesSource, version) -> + blockingToFlux { testSuiteRepository.findAllBySourceAndVersion(testSuitesSource, version) } + } + .map { it.toDto() } + .collectList() /** * @param id diff --git a/save-backend/src/main/kotlin/com/saveourtool/save/backend/service/TestSuitesSourceService.kt b/save-backend/src/main/kotlin/com/saveourtool/save/backend/service/TestSuitesSourceService.kt index 9753ac01ac..6fbc34b247 100644 --- a/save-backend/src/main/kotlin/com/saveourtool/save/backend/service/TestSuitesSourceService.kt +++ b/save-backend/src/main/kotlin/com/saveourtool/save/backend/service/TestSuitesSourceService.kt @@ -96,7 +96,7 @@ class TestSuitesSourceService( fun getStandardTestSuitesSources(): List { // FIXME: a hardcoded values for standard test suites // Will be removed in phase 3 - val organizationName = "Huawei" + val organizationName = "CQFN.org" val gitUrl = "https://github.com/saveourtool/save-cli" val branch = "main" val testRootPaths = listOf("examples/kotlin-diktat", "examples/discovery-test") diff --git a/save-backend/src/main/kotlin/com/saveourtool/save/backend/utils/ReactorUtils.kt b/save-backend/src/main/kotlin/com/saveourtool/save/backend/utils/ReactorUtils.kt index 2b5aad5d85..08cbb16145 100644 --- a/save-backend/src/main/kotlin/com/saveourtool/save/backend/utils/ReactorUtils.kt +++ b/save-backend/src/main/kotlin/com/saveourtool/save/backend/utils/ReactorUtils.kt @@ -12,6 +12,7 @@ import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity import reactor.core.publisher.Flux import reactor.core.publisher.Mono +import reactor.core.scheduler.Schedulers import reactor.kotlin.core.publisher.toFlux import reactor.kotlin.core.publisher.toMono @@ -92,3 +93,15 @@ fun T?.toMonoOrNotFound(message: String? = null) = toMono().switchI fun justOrNotFound(data: Optional, message: String? = null) = Mono.justOrEmpty(data).switchIfEmptyToNotFound { message } + +/** + * Taking from https://projectreactor.io/docs/core/release/reference/#faq.wrap-blocking + * + * @param supplier blocking operation like JDBC + */ +fun blockingToMono(supplier: () -> T): Mono = Mono.fromCallable(supplier).subscribeOn(Schedulers.boundedElastic()) + +/** + * @param supplier blocking operation like JDBC + */ +fun blockingToFlux(supplier: () -> Iterable): Flux = blockingToMono(supplier).flatMapIterable { it }