From 45b2fa36e142ff3c99025b1325b18f20091bf820 Mon Sep 17 00:00:00 2001 From: "Farre,Juan_Antonio (IT EDS) BI-ES-S" Date: Tue, 16 Jul 2024 11:22:15 +0200 Subject: [PATCH 01/16] Check DocGen service availability before generating documentation --- .../service/DocGenService.groovy | 8 +++-- .../usecase/DocGenUseCase.groovy | 18 ++++++++++ .../usecase/ServiceNotReadyException.groovy | 29 ++++++++++++++++ .../usecase/DocGenUseCaseSpec.groovy | 33 +++++++++++++------ .../usecase/LeVADocumentUseCaseSpec.groovy | 1 + 5 files changed, 77 insertions(+), 12 deletions(-) create mode 100644 src/org/ods/orchestration/usecase/ServiceNotReadyException.groovy diff --git a/src/org/ods/orchestration/service/DocGenService.groovy b/src/org/ods/orchestration/service/DocGenService.groovy index 92fbf210be..5af27d6e9d 100644 --- a/src/org/ods/orchestration/service/DocGenService.groovy +++ b/src/org/ods/orchestration/service/DocGenService.groovy @@ -7,8 +7,6 @@ import com.cloudbees.groovy.cps.NonCPS import groovy.json.JsonOutput import groovy.json.JsonSlurperClassic -import java.net.URI - import kong.unirest.Unirest import org.apache.http.client.utils.URIBuilder @@ -31,6 +29,12 @@ class DocGenService { } } + @NonCPS + int healthCheck() { + def response = Unirest.head("${this.baseURL}/health").asEmpty() + return response.getStatus() + } + @NonCPS byte[] createDocument(String type, String version, Map data) { def response = Unirest.post("${this.baseURL}/document") diff --git a/src/org/ods/orchestration/usecase/DocGenUseCase.groovy b/src/org/ods/orchestration/usecase/DocGenUseCase.groovy index 413235ed91..1e8a1f8395 100644 --- a/src/org/ods/orchestration/usecase/DocGenUseCase.groovy +++ b/src/org/ods/orchestration/usecase/DocGenUseCase.groovy @@ -17,6 +17,8 @@ import org.ods.orchestration.util.Project 'GStringAsMapKey', 'DuplicateMapLiteral']) abstract class DocGenUseCase { + private static final int MAX_RETRIES = 5 + private static final int RETRY_WAIT_SECONDS = 5 static final String RESURRECTED = "resurrected" protected Project project @@ -37,7 +39,23 @@ abstract class DocGenUseCase { this.jenkins = jenkins } + private int isServiceReady() { + int status + for (int i = 0; i < MAX_RETRIES; i++) { + status = this.docGen.healthCheck() + if (status == 200) { + break + } + sleep(RETRY_WAIT_SECONDS) + } + return status + } + String createDocument(String documentType, Map repo, Map data, Map files = [:], Closure modifier = null, String templateName = null, String watermarkText = null) { + int status = isServiceReady() + if (status != 200) { + throw new ServiceNotReadyException(status, "DocGen service is not ready.") + } // Create a PDF document via the DocGen service def document = this.docGen.createDocument(templateName ?: documentType, this.getDocumentTemplatesVersion(), data) diff --git a/src/org/ods/orchestration/usecase/ServiceNotReadyException.groovy b/src/org/ods/orchestration/usecase/ServiceNotReadyException.groovy new file mode 100644 index 0000000000..b258ec1610 --- /dev/null +++ b/src/org/ods/orchestration/usecase/ServiceNotReadyException.groovy @@ -0,0 +1,29 @@ +package org.ods.orchestration.usecase + +class ServiceNotReadyException extends Exception { + final int status + + ServiceNotReadyException(int status){ + this.status = status + } + + ServiceNotReadyException(int status, String message) { + super(message) + this.status = status + } + + ServiceNotReadyException(int status, Throwable cause) { + super(cause) + this.status = status + } + + ServiceNotReadyException(int status, String message, Throwable cause) { + super(message, cause) + this.status = status + } + + @Override + String toString() { + return super.toString() + "\nHTTP status: ${status}" + } +} diff --git a/test/groovy/org/ods/orchestration/usecase/DocGenUseCaseSpec.groovy b/test/groovy/org/ods/orchestration/usecase/DocGenUseCaseSpec.groovy index 273d0aa9b3..363ed60a22 100644 --- a/test/groovy/org/ods/orchestration/usecase/DocGenUseCaseSpec.groovy +++ b/test/groovy/org/ods/orchestration/usecase/DocGenUseCaseSpec.groovy @@ -58,10 +58,12 @@ class DocGenUseCaseSpec extends SpecHelper { pdf = Mock(PDFUtil) jenkins = Mock(JenkinsService) usecase = Spy(new DocGenUseCaseImpl(project, steps, util, docGen, nexus, pdf, jenkins)) + docGen.healthCheck() >> 200 } def "create document"() { given: + docGen.healthCheck() >> [201, 300, 400, 500, 200] // Test Parameters def logFile1 = Files.createTempFile("raw", ".log").toFile() << "Log File 1" def logFile2 = Files.createTempFile("raw", ".log").toFile() << "Log File 2" @@ -123,13 +125,24 @@ class DocGenUseCaseSpec extends SpecHelper { logFile2.delete() } - + def "create document when docgen not ready"() { + given: + docGen.healthCheck() >> [201, 300, 400, 100, 500] + + when: + usecase.createDocument(*_) + + then: + ServiceNotReadyException e = thrown() + e.getStatus() == 500 + } + def "create document and stash"() { given: // Test Parameters def logFile1 = Files.createTempFile("raw", ".log").toFile() << "Log File 1" def logFile2 = Files.createTempFile("raw", ".log").toFile() << "Log File 2" - + def documentType = "myDocumentType" def version = project.buildParams.version def repo = project.repositories.first() @@ -138,15 +151,15 @@ class DocGenUseCaseSpec extends SpecHelper { "raw/${logFile1.name}": logFile1.bytes, "raw/${logFile2.name}": logFile2.bytes ] - + // Argument Constraints def basename = "${documentType}-${project.key}-${repo.id}-${version}-${steps.env.BUILD_ID}" - + // Stubbed Method Responses def document = "PDF".bytes def archive = "Archive".bytes def nexusUri = new URI("http://nexus") - + when: def result = usecase.createDocument(documentType, repo, data, files) @@ -181,10 +194,10 @@ class DocGenUseCaseSpec extends SpecHelper { archive, "application/zip" ) >> nexusUri - + then: result == nexusUri.toString() - + cleanup: logFile1.delete() logFile2.delete() @@ -381,7 +394,7 @@ class DocGenUseCaseSpec extends SpecHelper { new File ("${path}/${docName}").write("test") def metadata = [:] - + when: usecase.createOverallDocument(templateName, documentType, metadata) @@ -432,11 +445,11 @@ class DocGenUseCaseSpec extends SpecHelper { def version = project.buildParams.version def build = "0815" def repo = project.repositories.first() - + repo.data.openshift = [:] when: def result = usecase.resurrectAndStashDocument(documentType, repo) - + then: result.found == false } diff --git a/test/groovy/org/ods/orchestration/usecase/LeVADocumentUseCaseSpec.groovy b/test/groovy/org/ods/orchestration/usecase/LeVADocumentUseCaseSpec.groovy index 799c04509e..c30e3aaccd 100644 --- a/test/groovy/org/ods/orchestration/usecase/LeVADocumentUseCaseSpec.groovy +++ b/test/groovy/org/ods/orchestration/usecase/LeVADocumentUseCaseSpec.groovy @@ -90,6 +90,7 @@ class LeVADocumentUseCaseSpec extends SpecHelper { jenkins.unstashFilesIntoPath(_, _, "SonarQube Report") >> true steps.getEnv() >> ['RELEASE_PARAM_VERSION': 'WIP'] stepsNoWip.getEnv() >> ['RELEASE_PARAM_VERSION': 'CHG00001'] + docGen.healthCheck() >> 200 } def "compute test discrepancies"() { From 0f5591a09a7f5cd18660a6fcadc12ce68e494db7 Mon Sep 17 00:00:00 2001 From: "Farre,Juan_Antonio (IT EDS) BI-ES-S" Date: Tue, 16 Jul 2024 11:25:26 +0200 Subject: [PATCH 02/16] Update change log --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c22c1a1dad..bd17826dfd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ ### Changed * Enhance SSDS Document Generation Performance using New Atlassian APIs ([#1084](https://github.com/opendevstack/ods-jenkins-shared-library/issues/1084)) +* Check DocGen service availability before generating documentation ([#1141](https://github.com/opendevstack/ods-jenkins-shared-library/pull/1141)) ### Fixed * Fix Tailor deployment drifts for D, Q envs ([#1055](https://github.com/opendevstack/ods-jenkins-shared-library/pull/1055)) From a7660403bf7ef7a65bbc75d4910a24bf8b544eb1 Mon Sep 17 00:00:00 2001 From: "Farre,Juan_Antonio (IT EDS) BI-ES-S" Date: Tue, 16 Jul 2024 11:41:22 +0200 Subject: [PATCH 03/16] Fix codenarc findings --- .../usecase/DocGenUseCase.groovy | 25 ++++++++++--------- .../usecase/LeVADocumentUseCase.groovy | 8 +++--- .../usecase/ServiceNotReadyException.groovy | 4 ++- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/org/ods/orchestration/usecase/DocGenUseCase.groovy b/src/org/ods/orchestration/usecase/DocGenUseCase.groovy index 1e8a1f8395..c5ebe34821 100644 --- a/src/org/ods/orchestration/usecase/DocGenUseCase.groovy +++ b/src/org/ods/orchestration/usecase/DocGenUseCase.groovy @@ -17,6 +17,7 @@ import org.ods.orchestration.util.Project 'GStringAsMapKey', 'DuplicateMapLiteral']) abstract class DocGenUseCase { + private static final int MAX_RETRIES = 5 private static final int RETRY_WAIT_SECONDS = 5 @@ -39,18 +40,6 @@ abstract class DocGenUseCase { this.jenkins = jenkins } - private int isServiceReady() { - int status - for (int i = 0; i < MAX_RETRIES; i++) { - status = this.docGen.healthCheck() - if (status == 200) { - break - } - sleep(RETRY_WAIT_SECONDS) - } - return status - } - String createDocument(String documentType, Map repo, Map data, Map files = [:], Closure modifier = null, String templateName = null, String watermarkText = null) { int status = isServiceReady() if (status != 200) { @@ -264,4 +253,16 @@ abstract class DocGenUseCase { abstract boolean shouldCreateArtifact (String documentType, Map repo) + private int isServiceReady() { + int status + for (int i = 0; i < MAX_RETRIES; i++) { + status = this.docGen.healthCheck() + if (status == 200) { + break + } + sleep(RETRY_WAIT_SECONDS) + } + return status + } + } diff --git a/src/org/ods/orchestration/usecase/LeVADocumentUseCase.groovy b/src/org/ods/orchestration/usecase/LeVADocumentUseCase.groovy index ec02672c0e..5800afb11a 100644 --- a/src/org/ods/orchestration/usecase/LeVADocumentUseCase.groovy +++ b/src/org/ods/orchestration/usecase/LeVADocumentUseCase.groovy @@ -1041,13 +1041,13 @@ class LeVADocumentUseCase extends DocGenUseCase { //Add break space in url in manufacturer def p = ~'https?://\\S*' def m = it.metadata.supplier =~ p - StringBuffer sb = new StringBuffer(); + StringBuffer sb = new StringBuffer() while (m.find()) { - String url = m.group(); + String url = m.group() url = url.replaceAll('/+', '$0\u200B') - m.appendReplacement(sb, url); + m.appendReplacement(sb, url) } - m.appendTail(sb); + m.appendTail(sb) clone.printsupplier = sb.toString() return clone diff --git a/src/org/ods/orchestration/usecase/ServiceNotReadyException.groovy b/src/org/ods/orchestration/usecase/ServiceNotReadyException.groovy index b258ec1610..4b290f1d7d 100644 --- a/src/org/ods/orchestration/usecase/ServiceNotReadyException.groovy +++ b/src/org/ods/orchestration/usecase/ServiceNotReadyException.groovy @@ -1,9 +1,10 @@ package org.ods.orchestration.usecase class ServiceNotReadyException extends Exception { + final int status - ServiceNotReadyException(int status){ + ServiceNotReadyException(int status) { this.status = status } @@ -26,4 +27,5 @@ class ServiceNotReadyException extends Exception { String toString() { return super.toString() + "\nHTTP status: ${status}" } + } From ab253c4b044cc66bb2a9a9211df85f118f511c77 Mon Sep 17 00:00:00 2001 From: "Farre,Juan_Antonio (IT EDS) BI-ES-S" Date: Tue, 16 Jul 2024 11:55:03 +0200 Subject: [PATCH 04/16] Fix codenarc findings --- src/org/ods/orchestration/service/DocGenService.groovy | 3 ++- .../usecase/BitbucketTraceabilityUseCase.groovy | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/org/ods/orchestration/service/DocGenService.groovy b/src/org/ods/orchestration/service/DocGenService.groovy index 5af27d6e9d..249fdbe3a1 100644 --- a/src/org/ods/orchestration/service/DocGenService.groovy +++ b/src/org/ods/orchestration/service/DocGenService.groovy @@ -45,7 +45,7 @@ class DocGenService { type: type, version: version ], - data: data + data: data, ])) .asString() @@ -69,4 +69,5 @@ class DocGenService { private static byte[] decodeBase64(String base64String) { return Base64.decoder.decode(base64String) } + } diff --git a/src/org/ods/orchestration/usecase/BitbucketTraceabilityUseCase.groovy b/src/org/ods/orchestration/usecase/BitbucketTraceabilityUseCase.groovy index 49e7cdfd45..96ddd4b775 100644 --- a/src/org/ods/orchestration/usecase/BitbucketTraceabilityUseCase.groovy +++ b/src/org/ods/orchestration/usecase/BitbucketTraceabilityUseCase.groovy @@ -115,10 +115,9 @@ class BitbucketTraceabilityUseCase { nextPageStart = pullRequests.nextPageStart } - records += pullRequests.values.collect { pullRequest -> - processPullRequest(token, repo, pullRequest)} - .flatten() - + records += pullRequests.values.collectMany { pullRequest -> + processPullRequest(token, repo, pullRequest) + } } return records } @@ -201,6 +200,7 @@ class BitbucketTraceabilityUseCase { Date dateObj = new Date(timestamp) return new SimpleDateFormat('yyyy-MM-dd', Locale.getDefault()).format(dateObj) } + } private class Developer { From 388660e15bd08e3cac4a787f63e3d62e2e019999 Mon Sep 17 00:00:00 2001 From: "Farre,Juan_Antonio (IT EDS) BI-ES-S" Date: Tue, 16 Jul 2024 11:59:23 +0200 Subject: [PATCH 05/16] Fix codenarc findings --- .../orchestration/usecase/BitbucketTraceabilityUseCase.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/ods/orchestration/usecase/BitbucketTraceabilityUseCase.groovy b/src/org/ods/orchestration/usecase/BitbucketTraceabilityUseCase.groovy index 96ddd4b775..37c587d1d3 100644 --- a/src/org/ods/orchestration/usecase/BitbucketTraceabilityUseCase.groovy +++ b/src/org/ods/orchestration/usecase/BitbucketTraceabilityUseCase.groovy @@ -200,7 +200,7 @@ class BitbucketTraceabilityUseCase { Date dateObj = new Date(timestamp) return new SimpleDateFormat('yyyy-MM-dd', Locale.getDefault()).format(dateObj) } - + } private class Developer { From 7de188b40bec1a2d411dc80bff0b58be5c6b8e99 Mon Sep 17 00:00:00 2001 From: "Farre,Juan_Antonio (IT EDS) BI-ES-S" Date: Tue, 16 Jul 2024 12:32:14 +0200 Subject: [PATCH 06/16] Fix unit tests --- build.gradle | 2 +- .../ods/orchestration/usecase/DocGenUseCase.groovy | 11 ++++------- .../orchestration/usecase/DocGenUseCaseSpec.groovy | 7 +++---- .../usecase/LeVADocumentUseCaseSpec.groovy | 1 - 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/build.gradle b/build.gradle index 033d410353..590b775174 100644 --- a/build.gradle +++ b/build.gradle @@ -139,7 +139,7 @@ codenarc { toolVersion = '1.6' configFile = file('codenarc.groovy') maxPriority1Violations = 0 - maxPriority2Violations = 1 + maxPriority2Violations = 0 maxPriority3Violations = 300 reportFormat = 'html' } diff --git a/src/org/ods/orchestration/usecase/DocGenUseCase.groovy b/src/org/ods/orchestration/usecase/DocGenUseCase.groovy index c5ebe34821..ea60ae4747 100644 --- a/src/org/ods/orchestration/usecase/DocGenUseCase.groovy +++ b/src/org/ods/orchestration/usecase/DocGenUseCase.groovy @@ -41,10 +41,7 @@ abstract class DocGenUseCase { } String createDocument(String documentType, Map repo, Map data, Map files = [:], Closure modifier = null, String templateName = null, String watermarkText = null) { - int status = isServiceReady() - if (status != 200) { - throw new ServiceNotReadyException(status, "DocGen service is not ready.") - } + checkServiceReadiness() // Create a PDF document via the DocGen service def document = this.docGen.createDocument(templateName ?: documentType, this.getDocumentTemplatesVersion(), data) @@ -253,16 +250,16 @@ abstract class DocGenUseCase { abstract boolean shouldCreateArtifact (String documentType, Map repo) - private int isServiceReady() { + private void checkServiceReadiness() { int status for (int i = 0; i < MAX_RETRIES; i++) { status = this.docGen.healthCheck() if (status == 200) { - break + return } sleep(RETRY_WAIT_SECONDS) } - return status + throw new ServiceNotReadyException(status, "DocGen service is not ready.") } } diff --git a/test/groovy/org/ods/orchestration/usecase/DocGenUseCaseSpec.groovy b/test/groovy/org/ods/orchestration/usecase/DocGenUseCaseSpec.groovy index 363ed60a22..b6c843f990 100644 --- a/test/groovy/org/ods/orchestration/usecase/DocGenUseCaseSpec.groovy +++ b/test/groovy/org/ods/orchestration/usecase/DocGenUseCaseSpec.groovy @@ -58,12 +58,11 @@ class DocGenUseCaseSpec extends SpecHelper { pdf = Mock(PDFUtil) jenkins = Mock(JenkinsService) usecase = Spy(new DocGenUseCaseImpl(project, steps, util, docGen, nexus, pdf, jenkins)) - docGen.healthCheck() >> 200 } def "create document"() { given: - docGen.healthCheck() >> [201, 300, 400, 500, 200] + docGen.healthCheck() >>> [201, 300, 400, 500, 200] // Test Parameters def logFile1 = Files.createTempFile("raw", ".log").toFile() << "Log File 1" def logFile2 = Files.createTempFile("raw", ".log").toFile() << "Log File 2" @@ -127,10 +126,10 @@ class DocGenUseCaseSpec extends SpecHelper { def "create document when docgen not ready"() { given: - docGen.healthCheck() >> [201, 300, 400, 100, 500] + docGen.healthCheck() >>> [201, 300, 400, 100, 500] when: - usecase.createDocument(*_) + usecase.createDocument(null, null, null) then: ServiceNotReadyException e = thrown() diff --git a/test/groovy/org/ods/orchestration/usecase/LeVADocumentUseCaseSpec.groovy b/test/groovy/org/ods/orchestration/usecase/LeVADocumentUseCaseSpec.groovy index c30e3aaccd..799c04509e 100644 --- a/test/groovy/org/ods/orchestration/usecase/LeVADocumentUseCaseSpec.groovy +++ b/test/groovy/org/ods/orchestration/usecase/LeVADocumentUseCaseSpec.groovy @@ -90,7 +90,6 @@ class LeVADocumentUseCaseSpec extends SpecHelper { jenkins.unstashFilesIntoPath(_, _, "SonarQube Report") >> true steps.getEnv() >> ['RELEASE_PARAM_VERSION': 'WIP'] stepsNoWip.getEnv() >> ['RELEASE_PARAM_VERSION': 'CHG00001'] - docGen.healthCheck() >> 200 } def "compute test discrepancies"() { From 57a610a2e66717a4fca291951abeec7b603d9339 Mon Sep 17 00:00:00 2001 From: "Farre,Juan_Antonio (IT EDS) BI-ES-S" Date: Tue, 16 Jul 2024 12:42:42 +0200 Subject: [PATCH 07/16] Fix unit tests --- .../org/ods/orchestration/usecase/DocGenUseCaseSpec.groovy | 7 +++---- .../orchestration/usecase/LeVADocumentUseCaseSpec.groovy | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/groovy/org/ods/orchestration/usecase/DocGenUseCaseSpec.groovy b/test/groovy/org/ods/orchestration/usecase/DocGenUseCaseSpec.groovy index b6c843f990..7e777a9d50 100644 --- a/test/groovy/org/ods/orchestration/usecase/DocGenUseCaseSpec.groovy +++ b/test/groovy/org/ods/orchestration/usecase/DocGenUseCaseSpec.groovy @@ -58,11 +58,11 @@ class DocGenUseCaseSpec extends SpecHelper { pdf = Mock(PDFUtil) jenkins = Mock(JenkinsService) usecase = Spy(new DocGenUseCaseImpl(project, steps, util, docGen, nexus, pdf, jenkins)) + docGen.healthCheck() >> 200 } def "create document"() { given: - docGen.healthCheck() >>> [201, 300, 400, 500, 200] // Test Parameters def logFile1 = Files.createTempFile("raw", ".log").toFile() << "Log File 1" def logFile2 = Files.createTempFile("raw", ".log").toFile() << "Log File 2" @@ -89,6 +89,7 @@ class DocGenUseCaseSpec extends SpecHelper { then: 1 * docGen.createDocument(documentType, "0.1", data) >> document + 5 * docGen.healthCheck() >>> [201, 300, 400, 500, 200] then: 1 * usecase.getDocumentBasename(documentType, version, steps.env.BUILD_ID,repo) @@ -125,13 +126,11 @@ class DocGenUseCaseSpec extends SpecHelper { } def "create document when docgen not ready"() { - given: - docGen.healthCheck() >>> [201, 300, 400, 100, 500] - when: usecase.createDocument(null, null, null) then: + 5 * docGen.healthCheck() >>> [201, 300, 400, 100, 500] ServiceNotReadyException e = thrown() e.getStatus() == 500 } diff --git a/test/groovy/org/ods/orchestration/usecase/LeVADocumentUseCaseSpec.groovy b/test/groovy/org/ods/orchestration/usecase/LeVADocumentUseCaseSpec.groovy index 799c04509e..c30e3aaccd 100644 --- a/test/groovy/org/ods/orchestration/usecase/LeVADocumentUseCaseSpec.groovy +++ b/test/groovy/org/ods/orchestration/usecase/LeVADocumentUseCaseSpec.groovy @@ -90,6 +90,7 @@ class LeVADocumentUseCaseSpec extends SpecHelper { jenkins.unstashFilesIntoPath(_, _, "SonarQube Report") >> true steps.getEnv() >> ['RELEASE_PARAM_VERSION': 'WIP'] stepsNoWip.getEnv() >> ['RELEASE_PARAM_VERSION': 'CHG00001'] + docGen.healthCheck() >> 200 } def "compute test discrepancies"() { From f61b0203fa4f8b0bd7ff272556e79a5b9aa3143a Mon Sep 17 00:00:00 2001 From: "Farre,Juan_Antonio (IT EDS) BI-ES-S" Date: Wed, 24 Jul 2024 18:07:18 +0200 Subject: [PATCH 08/16] Fix problem with CPS --- src/org/ods/orchestration/usecase/DocGenUseCase.groovy | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/org/ods/orchestration/usecase/DocGenUseCase.groovy b/src/org/ods/orchestration/usecase/DocGenUseCase.groovy index ea60ae4747..39e2bab61e 100644 --- a/src/org/ods/orchestration/usecase/DocGenUseCase.groovy +++ b/src/org/ods/orchestration/usecase/DocGenUseCase.groovy @@ -1,5 +1,6 @@ package org.ods.orchestration.usecase +import com.cloudbees.groovy.cps.NonCPS import groovy.json.JsonOutput import org.ods.orchestration.service.DocGenService @@ -250,6 +251,7 @@ abstract class DocGenUseCase { abstract boolean shouldCreateArtifact (String documentType, Map repo) + @NonCPS private void checkServiceReadiness() { int status for (int i = 0; i < MAX_RETRIES; i++) { From f3e09e533be0f390cac709a54fd03a59d4eed8b4 Mon Sep 17 00:00:00 2001 From: "Farre,Juan_Antonio (IT EDS) BI-ES-S" Date: Thu, 25 Jul 2024 11:28:14 +0200 Subject: [PATCH 09/16] Fix visibility problem --- src/org/ods/orchestration/usecase/DocGenUseCase.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/ods/orchestration/usecase/DocGenUseCase.groovy b/src/org/ods/orchestration/usecase/DocGenUseCase.groovy index 39e2bab61e..b647947a8e 100644 --- a/src/org/ods/orchestration/usecase/DocGenUseCase.groovy +++ b/src/org/ods/orchestration/usecase/DocGenUseCase.groovy @@ -252,7 +252,7 @@ abstract class DocGenUseCase { abstract boolean shouldCreateArtifact (String documentType, Map repo) @NonCPS - private void checkServiceReadiness() { + protected void checkServiceReadiness() { int status for (int i = 0; i < MAX_RETRIES; i++) { status = this.docGen.healthCheck() From 4eb09d4baa5fa8e832cf1f9215e6ee426aeebe55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Farr=C3=A9?= <13270880+jafarre-bi@users.noreply.github.com> Date: Mon, 2 Sep 2024 10:44:19 +0200 Subject: [PATCH 10/16] Use get for DocGenService healthCheck Head is not supported by the docgen service --- src/org/ods/orchestration/service/DocGenService.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/ods/orchestration/service/DocGenService.groovy b/src/org/ods/orchestration/service/DocGenService.groovy index 249fdbe3a1..f25ad9c7af 100644 --- a/src/org/ods/orchestration/service/DocGenService.groovy +++ b/src/org/ods/orchestration/service/DocGenService.groovy @@ -31,7 +31,7 @@ class DocGenService { @NonCPS int healthCheck() { - def response = Unirest.head("${this.baseURL}/health").asEmpty() + def response = Unirest.get("${this.baseURL}/health").asEmpty() return response.getStatus() } From 91550aef34e29cc84900599a8301cfbb6c7fd458 Mon Sep 17 00:00:00 2001 From: "Farre,Juan_Antonio (IT EDS) BI-ES-S" Date: Mon, 2 Sep 2024 11:12:35 +0200 Subject: [PATCH 11/16] Catch possible exceptions thrown by DocGenService.healthCheck --- .../ods/orchestration/usecase/DocGenUseCase.groovy | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/org/ods/orchestration/usecase/DocGenUseCase.groovy b/src/org/ods/orchestration/usecase/DocGenUseCase.groovy index b647947a8e..c6c4ed38b9 100644 --- a/src/org/ods/orchestration/usecase/DocGenUseCase.groovy +++ b/src/org/ods/orchestration/usecase/DocGenUseCase.groovy @@ -255,9 +255,16 @@ abstract class DocGenUseCase { protected void checkServiceReadiness() { int status for (int i = 0; i < MAX_RETRIES; i++) { - status = this.docGen.healthCheck() - if (status == 200) { - return + try { + status = this.docGen.healthCheck() + if (status == 200) { + return + } + } catch (e) { + // There may be a lower-level error, such as a connection reset, for which there is no HTTP status. + // In these cases, healthCheck throws an exception. + // Given the lack of documentation about the possible exceptions, we have to consider all of them + // as retryable. Anyway, we have a MAX_RETRIES. } sleep(RETRY_WAIT_SECONDS) } From 5853331324e284da3bf3668ef90b0b181c16c74e Mon Sep 17 00:00:00 2001 From: "Farre,Juan_Antonio (IT EDS) BI-ES-S" Date: Mon, 2 Sep 2024 11:20:03 +0200 Subject: [PATCH 12/16] Mark the catch argument as ignored --- src/org/ods/orchestration/usecase/DocGenUseCase.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/ods/orchestration/usecase/DocGenUseCase.groovy b/src/org/ods/orchestration/usecase/DocGenUseCase.groovy index c6c4ed38b9..a3fd741f59 100644 --- a/src/org/ods/orchestration/usecase/DocGenUseCase.groovy +++ b/src/org/ods/orchestration/usecase/DocGenUseCase.groovy @@ -260,7 +260,7 @@ abstract class DocGenUseCase { if (status == 200) { return } - } catch (e) { + } catch (ignored) { // There may be a lower-level error, such as a connection reset, for which there is no HTTP status. // In these cases, healthCheck throws an exception. // Given the lack of documentation about the possible exceptions, we have to consider all of them From 0b3c95edd1b583e7904e741565e2b4356fc639e0 Mon Sep 17 00:00:00 2001 From: "Farre,Juan_Antonio (IT EDS) BI-ES-S" Date: Mon, 2 Sep 2024 11:25:13 +0200 Subject: [PATCH 13/16] Retry connection to the DocGen service for up to two minutes --- src/org/ods/orchestration/usecase/DocGenUseCase.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/ods/orchestration/usecase/DocGenUseCase.groovy b/src/org/ods/orchestration/usecase/DocGenUseCase.groovy index a3fd741f59..edc42c5e20 100644 --- a/src/org/ods/orchestration/usecase/DocGenUseCase.groovy +++ b/src/org/ods/orchestration/usecase/DocGenUseCase.groovy @@ -19,7 +19,7 @@ import org.ods.orchestration.util.Project 'DuplicateMapLiteral']) abstract class DocGenUseCase { - private static final int MAX_RETRIES = 5 + private static final int MAX_RETRIES = 24 private static final int RETRY_WAIT_SECONDS = 5 static final String RESURRECTED = "resurrected" From db09f6855c9f182fc0e2b267fef40849b5c9023d Mon Sep 17 00:00:00 2001 From: "Farre,Juan_Antonio (IT EDS) BI-ES-S" Date: Mon, 2 Sep 2024 11:34:45 +0200 Subject: [PATCH 14/16] Make checkServiceReadiness CPS so that it can execute a sleep --- src/org/ods/orchestration/usecase/DocGenUseCase.groovy | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/org/ods/orchestration/usecase/DocGenUseCase.groovy b/src/org/ods/orchestration/usecase/DocGenUseCase.groovy index edc42c5e20..4f5d39fc68 100644 --- a/src/org/ods/orchestration/usecase/DocGenUseCase.groovy +++ b/src/org/ods/orchestration/usecase/DocGenUseCase.groovy @@ -1,6 +1,5 @@ package org.ods.orchestration.usecase -import com.cloudbees.groovy.cps.NonCPS import groovy.json.JsonOutput import org.ods.orchestration.service.DocGenService @@ -19,7 +18,7 @@ import org.ods.orchestration.util.Project 'DuplicateMapLiteral']) abstract class DocGenUseCase { - private static final int MAX_RETRIES = 24 + private static final int MAX_RETRIES = 12 private static final int RETRY_WAIT_SECONDS = 5 static final String RESURRECTED = "resurrected" @@ -251,7 +250,6 @@ abstract class DocGenUseCase { abstract boolean shouldCreateArtifact (String documentType, Map repo) - @NonCPS protected void checkServiceReadiness() { int status for (int i = 0; i < MAX_RETRIES; i++) { From ecdcbdc01f58c8ad8e8dcef02de6407497459d44 Mon Sep 17 00:00:00 2001 From: "Farre,Juan_Antonio (IT EDS) BI-ES-S" Date: Mon, 2 Sep 2024 11:46:05 +0200 Subject: [PATCH 15/16] Making it noncps again and using Thread.sleep instead --- src/org/ods/orchestration/usecase/DocGenUseCase.groovy | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/org/ods/orchestration/usecase/DocGenUseCase.groovy b/src/org/ods/orchestration/usecase/DocGenUseCase.groovy index 4f5d39fc68..1d5321231e 100644 --- a/src/org/ods/orchestration/usecase/DocGenUseCase.groovy +++ b/src/org/ods/orchestration/usecase/DocGenUseCase.groovy @@ -1,5 +1,6 @@ package org.ods.orchestration.usecase +import com.cloudbees.groovy.cps.NonCPS import groovy.json.JsonOutput import org.ods.orchestration.service.DocGenService @@ -250,6 +251,7 @@ abstract class DocGenUseCase { abstract boolean shouldCreateArtifact (String documentType, Map repo) + @NonCPS protected void checkServiceReadiness() { int status for (int i = 0; i < MAX_RETRIES; i++) { @@ -264,7 +266,7 @@ abstract class DocGenUseCase { // Given the lack of documentation about the possible exceptions, we have to consider all of them // as retryable. Anyway, we have a MAX_RETRIES. } - sleep(RETRY_WAIT_SECONDS) + Thread.sleep(RETRY_WAIT_SECONDS) } throw new ServiceNotReadyException(status, "DocGen service is not ready.") } From f4e897f7a922243fd1fd953995b90de20d1791ae Mon Sep 17 00:00:00 2001 From: "Farre,Juan_Antonio (IT EDS) BI-ES-S" Date: Mon, 2 Sep 2024 11:55:41 +0200 Subject: [PATCH 16/16] Sleep timeout in millis --- src/org/ods/orchestration/usecase/DocGenUseCase.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/org/ods/orchestration/usecase/DocGenUseCase.groovy b/src/org/ods/orchestration/usecase/DocGenUseCase.groovy index 1d5321231e..84c69eeb5b 100644 --- a/src/org/ods/orchestration/usecase/DocGenUseCase.groovy +++ b/src/org/ods/orchestration/usecase/DocGenUseCase.groovy @@ -20,7 +20,7 @@ import org.ods.orchestration.util.Project abstract class DocGenUseCase { private static final int MAX_RETRIES = 12 - private static final int RETRY_WAIT_SECONDS = 5 + private static final long RETRY_WAIT_MILLISECONDS = 5000L static final String RESURRECTED = "resurrected" protected Project project @@ -266,7 +266,7 @@ abstract class DocGenUseCase { // Given the lack of documentation about the possible exceptions, we have to consider all of them // as retryable. Anyway, we have a MAX_RETRIES. } - Thread.sleep(RETRY_WAIT_SECONDS) + sleep(RETRY_WAIT_MILLISECONDS) } throw new ServiceNotReadyException(status, "DocGen service is not ready.") }