diff --git a/.github/workflows/build.from.developer.branch.deploy.to.dev.yml b/.github/workflows/build.from.developer.branch.deploy.to.dev.yml index 8e79bee..5048d46 100644 --- a/.github/workflows/build.from.developer.branch.deploy.to.dev.yml +++ b/.github/workflows/build.from.developer.branch.deploy.to.dev.yml @@ -24,9 +24,10 @@ env: MIN_CPU: "30m" MAX_CPU: "120m" MIN_MEM: "350Mi" - MAX_MEM: "900Mi" + MAX_MEM: "1200Mi" MIN_REPLICAS: "3" MAX_REPLICAS: "5" + STORAGE_LIMIT: 16Gi on: # https://docs.github.com/en/actions/reference/events-that-trigger-workflows @@ -115,7 +116,7 @@ jobs: oc -n ${{ env.OPENSHIFT_NAMESPACE }} tag ${{ steps.push-image.outputs.registry-path }} ${{ env.REPO_NAME }}:${{ env.TAG }} # Process and apply deployment template - oc process -f tools/openshift/api.dc.yaml -p IS_NAMESPACE=${{ env.OPENSHIFT_NAMESPACE }} -p REPO_NAME=${{ env.REPO_NAME }} -p TAG_NAME=${{ env.TAG }} -p HOST_ROUTE=${{ env.REPO_NAME }}-${{ env.OPENSHIFT_NAMESPACE }}.${{ env.APP_DOMAIN }} -p MIN_REPLICAS=${{ env.MIN_REPLICAS }} -p MAX_REPLICAS=${{ env.MAX_REPLICAS }} -p MIN_CPU=${{ env.MIN_CPU }} -p MAX_CPU=${{ env.MAX_CPU }} -p MIN_MEM=${{ env.MIN_MEM }} -p MAX_MEM=${{ env.MAX_MEM }} \ + oc process -f tools/openshift/api.dc.yaml -p IS_NAMESPACE=${{ env.OPENSHIFT_NAMESPACE }} -p REPO_NAME=${{ env.REPO_NAME }} -p TAG_NAME=${{ env.TAG }} -p HOST_ROUTE=${{ env.REPO_NAME }}-${{ env.OPENSHIFT_NAMESPACE }}.${{ env.APP_DOMAIN }} -p MIN_REPLICAS=${{ env.MIN_REPLICAS }} -p MAX_REPLICAS=${{ env.MAX_REPLICAS }} -p MIN_CPU=${{ env.MIN_CPU }} -p MAX_CPU=${{ env.MAX_CPU }} -p MIN_MEM=${{ env.MIN_MEM }} -p MAX_MEM=${{ env.MAX_MEM }} -p STORAGE_LIMIT=${{ env.STORAGE_LIMIT }} \ | oc apply -f - # Start rollout (if necessary) and follow it diff --git a/.github/workflows/build.from.main.branch.deploy.to.dev.yml b/.github/workflows/build.from.main.branch.deploy.to.dev.yml index 1082f7c..6d2d656 100644 --- a/.github/workflows/build.from.main.branch.deploy.to.dev.yml +++ b/.github/workflows/build.from.main.branch.deploy.to.dev.yml @@ -25,9 +25,10 @@ env: MIN_CPU: "30m" MAX_CPU: "120m" MIN_MEM: "350Mi" - MAX_MEM: "900Mi" + MAX_MEM: "1200Mi" MIN_REPLICAS: "3" MAX_REPLICAS: "5" + STORAGE_LIMIT: 16Gi on: # https://docs.github.com/en/actions/reference/events-that-trigger-workflows @@ -105,7 +106,7 @@ jobs: oc -n ${{ env.OPENSHIFT_NAMESPACE }} tag ${{ steps.push-image.outputs.registry-path }} ${{ env.REPO_NAME }}:${{ env.TAG }} # Process and apply deployment template - oc process -f tools/openshift/api.dc.yaml -p IS_NAMESPACE=${{ env.OPENSHIFT_NAMESPACE }} -p REPO_NAME=${{ env.REPO_NAME }} -p TAG_NAME=${{ env.TAG }} -p HOST_ROUTE=${{ env.REPO_NAME }}-${{ env.OPENSHIFT_NAMESPACE }}.${{ env.APP_DOMAIN }} -p MIN_REPLICAS=${{ env.MIN_REPLICAS }} -p MAX_REPLICAS=${{ env.MAX_REPLICAS }} -p MIN_CPU=${{ env.MIN_CPU }} -p MAX_CPU=${{ env.MAX_CPU }} -p MIN_MEM=${{ env.MIN_MEM }} -p MAX_MEM=${{ env.MAX_MEM }} \ + oc process -f tools/openshift/api.dc.yaml -p IS_NAMESPACE=${{ env.OPENSHIFT_NAMESPACE }} -p REPO_NAME=${{ env.REPO_NAME }} -p TAG_NAME=${{ env.TAG }} -p HOST_ROUTE=${{ env.REPO_NAME }}-${{ env.OPENSHIFT_NAMESPACE }}.${{ env.APP_DOMAIN }} -p MIN_REPLICAS=${{ env.MIN_REPLICAS }} -p MAX_REPLICAS=${{ env.MAX_REPLICAS }} -p MIN_CPU=${{ env.MIN_CPU }} -p MAX_CPU=${{ env.MAX_CPU }} -p MIN_MEM=${{ env.MIN_MEM }} -p MAX_MEM=${{ env.MAX_MEM }} -p STORAGE_LIMIT=${{ env.STORAGE_LIMIT }} \ | oc apply -f - # Start rollout (if necessary) and follow it diff --git a/.github/workflows/build.from.release.branch.deploy.to.dev.yml b/.github/workflows/build.from.release.branch.deploy.to.dev.yml index 1e231a3..b87d2ef 100644 --- a/.github/workflows/build.from.release.branch.deploy.to.dev.yml +++ b/.github/workflows/build.from.release.branch.deploy.to.dev.yml @@ -24,9 +24,10 @@ env: MIN_CPU: "30m" MAX_CPU: "120m" MIN_MEM: "350Mi" - MAX_MEM: "900Mi" + MAX_MEM: "1200Mi" MIN_REPLICAS: "3" MAX_REPLICAS: "5" + STORAGE_LIMIT: 16Gi on: # https://docs.github.com/en/actions/reference/events-that-trigger-workflows @@ -112,7 +113,7 @@ jobs: oc -n ${{ env.OPENSHIFT_NAMESPACE }} tag ${{ steps.push-image.outputs.registry-path }} ${{ env.REPO_NAME }}:${{ env.TAG }} # Process and apply deployment template - oc process -f tools/openshift/api.dc.yaml -p IS_NAMESPACE=${{ env.OPENSHIFT_NAMESPACE }} -p REPO_NAME=${{ env.REPO_NAME }} -p TAG_NAME=${{ env.TAG }} -p HOST_ROUTE=${{ env.REPO_NAME }}-${{ env.OPENSHIFT_NAMESPACE }}.${{ env.APP_DOMAIN }} -p MIN_REPLICAS=${{ env.MIN_REPLICAS }} -p MAX_REPLICAS=${{ env.MAX_REPLICAS }} -p MIN_CPU=${{ env.MIN_CPU }} -p MAX_CPU=${{ env.MAX_CPU }} -p MIN_MEM=${{ env.MIN_MEM }} -p MAX_MEM=${{ env.MAX_MEM }} \ + oc process -f tools/openshift/api.dc.yaml -p IS_NAMESPACE=${{ env.OPENSHIFT_NAMESPACE }} -p REPO_NAME=${{ env.REPO_NAME }} -p TAG_NAME=${{ env.TAG }} -p HOST_ROUTE=${{ env.REPO_NAME }}-${{ env.OPENSHIFT_NAMESPACE }}.${{ env.APP_DOMAIN }} -p MIN_REPLICAS=${{ env.MIN_REPLICAS }} -p MAX_REPLICAS=${{ env.MAX_REPLICAS }} -p MIN_CPU=${{ env.MIN_CPU }} -p MAX_CPU=${{ env.MAX_CPU }} -p MIN_MEM=${{ env.MIN_MEM }} -p MAX_MEM=${{ env.MAX_MEM }} -p STORAGE_LIMIT=${{ env.STORAGE_LIMIT }} \ | oc apply -f - # Start rollout (if necessary) and follow it diff --git a/.github/workflows/deploy_prod.yml b/.github/workflows/deploy_prod.yml index d3511e1..73b9e47 100644 --- a/.github/workflows/deploy_prod.yml +++ b/.github/workflows/deploy_prod.yml @@ -19,9 +19,10 @@ env: MIN_CPU: "30m" MAX_CPU: "120m" MIN_MEM: "350Mi" - MAX_MEM: "900Mi" + MAX_MEM: "1200Mi" MIN_REPLICAS: "3" MAX_REPLICAS: "5" + STORAGE_LIMIT: 32Gi on: @@ -67,7 +68,7 @@ jobs: oc tag ${{ env.NAMESPACE }}-test/${{ env.REPO_NAME }}:${{ steps.get-latest-tag.outputs.tag }} ${{ env.NAMESPACE }}-prod/${{ env.REPO_NAME }}:${{ steps.get-latest-tag.outputs.tag }} # Process and apply deployment template - oc process -f tools/openshift/api.dc.yaml -p IS_NAMESPACE=${{ env.OPENSHIFT_NAMESPACE }} -p REPO_NAME=${{ env.REPO_NAME }} -p TAG_NAME=${{ steps.get-latest-tag.outputs.tag }} -p HOST_ROUTE=${{ env.REPO_NAME }}-${{ env.OPENSHIFT_NAMESPACE }}.${{ env.APP_DOMAIN }} -p MIN_REPLICAS=${{ env.MIN_REPLICAS }} -p MAX_REPLICAS=${{ env.MAX_REPLICAS }} -p MIN_CPU=${{ env.MIN_CPU }} -p MAX_CPU=${{ env.MAX_CPU }} -p MIN_MEM=${{ env.MIN_MEM }} -p MAX_MEM=${{ env.MAX_MEM }} \ + oc process -f tools/openshift/api.dc.yaml -p IS_NAMESPACE=${{ env.OPENSHIFT_NAMESPACE }} -p REPO_NAME=${{ env.REPO_NAME }} -p TAG_NAME=${{ steps.get-latest-tag.outputs.tag }} -p HOST_ROUTE=${{ env.REPO_NAME }}-${{ env.OPENSHIFT_NAMESPACE }}.${{ env.APP_DOMAIN }} -p MIN_REPLICAS=${{ env.MIN_REPLICAS }} -p MAX_REPLICAS=${{ env.MAX_REPLICAS }} -p MIN_CPU=${{ env.MIN_CPU }} -p MAX_CPU=${{ env.MAX_CPU }} -p MIN_MEM=${{ env.MIN_MEM }} -p MAX_MEM=${{ env.MAX_MEM }} -p STORAGE_LIMIT=${{ env.STORAGE_LIMIT }} \ | oc apply -f - # Start rollout (if necessary) and follow it diff --git a/.github/workflows/deploy_test.yml b/.github/workflows/deploy_test.yml index ecd23cf..1574b3b 100644 --- a/.github/workflows/deploy_test.yml +++ b/.github/workflows/deploy_test.yml @@ -19,9 +19,10 @@ env: MIN_CPU: "30m" MAX_CPU: "120m" MIN_MEM: "350Mi" - MAX_MEM: "900Mi" + MAX_MEM: "1200Mi" MIN_REPLICAS: "3" MAX_REPLICAS: "5" + STORAGE_LIMIT: 32Gi on: @@ -67,7 +68,7 @@ jobs: oc tag ${{ env.NAMESPACE }}-dev/${{ env.REPO_NAME }}:${{ steps.get-latest-tag.outputs.tag }} ${{ env.NAMESPACE }}-test/${{ env.REPO_NAME }}:${{ steps.get-latest-tag.outputs.tag }} # Process and apply deployment template - oc process -f tools/openshift/api.dc.yaml -p IS_NAMESPACE=${{ env.OPENSHIFT_NAMESPACE }} -p REPO_NAME=${{ env.REPO_NAME }} -p TAG_NAME=${{ steps.get-latest-tag.outputs.tag }} -p HOST_ROUTE=${{ env.REPO_NAME }}-${{ env.OPENSHIFT_NAMESPACE }}.${{ env.APP_DOMAIN }} -p MIN_REPLICAS=${{ env.MIN_REPLICAS }} -p MAX_REPLICAS=${{ env.MAX_REPLICAS }} -p MIN_CPU=${{ env.MIN_CPU }} -p MAX_CPU=${{ env.MAX_CPU }} -p MIN_MEM=${{ env.MIN_MEM }} -p MAX_MEM=${{ env.MAX_MEM }} \ + oc process -f tools/openshift/api.dc.yaml -p IS_NAMESPACE=${{ env.OPENSHIFT_NAMESPACE }} -p REPO_NAME=${{ env.REPO_NAME }} -p TAG_NAME=${{ steps.get-latest-tag.outputs.tag }} -p HOST_ROUTE=${{ env.REPO_NAME }}-${{ env.OPENSHIFT_NAMESPACE }}.${{ env.APP_DOMAIN }} -p MIN_REPLICAS=${{ env.MIN_REPLICAS }} -p MAX_REPLICAS=${{ env.MAX_REPLICAS }} -p MIN_CPU=${{ env.MIN_CPU }} -p MAX_CPU=${{ env.MAX_CPU }} -p MIN_MEM=${{ env.MIN_MEM }} -p MAX_MEM=${{ env.MAX_MEM }} -p STORAGE_LIMIT=${{ env.STORAGE_LIMIT }} \ | oc apply -f - # Start rollout (if necessary) and follow it diff --git a/Dockerfile b/Dockerfile index 9561aa7..ca8ce55 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,7 +14,7 @@ ARG DEPENDENCY=/workspace/app/target/dependency COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app -ENTRYPOINT ["java","-Duser.name=EDUC_GRAD_BUSINESS_API","-Xms700m","-Xmx700m","-XX:TieredStopAtLevel=1",\ +ENTRYPOINT ["java","-Duser.name=EDUC_GRAD_BUSINESS_API","-Xms1024m","-Xmx1024m","-XX:TieredStopAtLevel=1",\ "-XX:+UseParallelGC","-XX:MinHeapFreeRatio=20","-XX:MaxHeapFreeRatio=40","-XX:GCTimeRatio=4",\ "-XX:AdaptiveSizePolicyWeight=90","-XX:MaxMetaspaceSize=300m","-XX:ParallelGCThreads=1",\ "-Djava.util.concurrent.ForkJoinPool.common.parallelism=1","-XX:CICompilerCount=2",\ diff --git a/api/src/main/java/ca/bc/gov/educ/api/gradbusiness/service/GradBusinessService.java b/api/src/main/java/ca/bc/gov/educ/api/gradbusiness/service/GradBusinessService.java index 3c8690c..4382f96 100644 --- a/api/src/main/java/ca/bc/gov/educ/api/gradbusiness/service/GradBusinessService.java +++ b/api/src/main/java/ca/bc/gov/educ/api/gradbusiness/service/GradBusinessService.java @@ -23,10 +23,10 @@ import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.client.WebClient; -import java.io.FileOutputStream; +import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.io.OutputStream; +import java.nio.file.Files; import java.util.*; import java.util.concurrent.CompletableFuture; @@ -42,7 +42,7 @@ public class GradBusinessService { private static final String APPLICATION_JSON = "application/json"; private static final String APPLICATION_PDF = "application/pdf"; private static final String ACCEPT = "*/*"; - private static final String TMP = "/tmp"; + private static final String TMP = File.separator + "tmp"; /** * The Web client. */ @@ -292,9 +292,10 @@ public ResponseEntity getStudentTranscriptPDFByType(String pen, String t private void getStudentAchievementReports(List> partitions, List locations) { logger.debug("******** Getting Student Achievement Reports ******"); for(List studentList: partitions) { + String accessToken = tokenUtils.getAccessToken(); logger.debug("******** Run partition with {} students ******", studentList.size()); List> futures = studentList.stream() - .map(studentGuid -> CompletableFuture.supplyAsync(() -> getStudentAchievementReport(studentGuid))) + .map(studentGuid -> CompletableFuture.supplyAsync(() -> getStudentAchievementReport(studentGuid, accessToken))) .toList(); CompletableFuture allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()])); CompletableFuture> result = allFutures.thenApply(v -> futures.stream() @@ -305,10 +306,10 @@ private void getStudentAchievementReports(List> partitions, List h.setBearerAuth(accessTokenNext)).retrieve().bodyToMono(InputStreamResource.class).block(); + String finalAccessToken = tokenUtils.isTokenExpired() ? tokenUtils.getAccessToken() : accessToken; + InputStreamResource result = webClient.get().uri(String.format(educGraduationApiConstants.getStudentCredentialByType(), studentGuid, "ACHV")).headers(h -> h.setBearerAuth(finalAccessToken)).retrieve().bodyToMono(InputStreamResource.class).block(); if (result != null) { logger.debug("******** Fetched Achievement Report for {} ******", studentGuid); return result.getInputStream(); @@ -346,8 +347,9 @@ protected ResponseEntity getInternalServerErrorResponse(Throwable t) { private ResponseEntity handleBinaryResponse(byte[] resultBinary, String reportFile, MediaType contentType) { ResponseEntity response; - if(resultBinary.length > 0) { + String fileType = contentType.getSubtype().toUpperCase(); + logger.debug("Sending {} response {} KB", fileType, resultBinary.length/(1024)); HttpHeaders headers = new HttpHeaders(); headers.add("Content-Disposition", "inline; filename=" + reportFile); response = ResponseEntity @@ -363,9 +365,14 @@ private ResponseEntity handleBinaryResponse(byte[] resultBinary, String private void saveBinaryResponseToFile(byte[] resultBinary, String reportFile) throws IOException { if(resultBinary.length > 0) { - try (OutputStream out = new FileOutputStream(TMP + "/" + reportFile)) { - out.write(resultBinary); + String pathToFile = TMP + File.separator + reportFile; + logger.debug("Save generated PDF {} on the file system", reportFile); + File fileToSave = new File(pathToFile); + if(Files.deleteIfExists(fileToSave.toPath())) { + logger.debug("Delete existing PDF {}", reportFile); } + Files.write(fileToSave.toPath(), resultBinary); + logger.debug("PDF {} saved successfully", pathToFile); } } } diff --git a/api/src/main/java/ca/bc/gov/educ/api/gradbusiness/util/TokenUtils.java b/api/src/main/java/ca/bc/gov/educ/api/gradbusiness/util/TokenUtils.java index 18ea101..d3d64c3 100644 --- a/api/src/main/java/ca/bc/gov/educ/api/gradbusiness/util/TokenUtils.java +++ b/api/src/main/java/ca/bc/gov/educ/api/gradbusiness/util/TokenUtils.java @@ -37,8 +37,12 @@ public String getAccessToken() { return this.fetchAccessToken(); } + public boolean isTokenExpired() { + return responseObjCache.isExpired(); + } + private ResponseObj getTokenResponseObject() { - if(responseObjCache.isExpired()){ + if(isTokenExpired()){ responseObjCache.setResponseObj(getResponseObj()); } return responseObjCache.getResponseObj(); diff --git a/tools/openshift/api.dc.yaml b/tools/openshift/api.dc.yaml index 3de6e99..8f08146 100644 --- a/tools/openshift/api.dc.yaml +++ b/tools/openshift/api.dc.yaml @@ -54,6 +54,8 @@ objects: volumeMounts: - name: log-storage mountPath: /logs + - name: business-data + mountPath: /tmp ports: - containerPort: ${{CONTAINER_PORT}} protocol: TCP @@ -115,6 +117,9 @@ objects: - name: flb-sc-config-volume configMap: name: "${REPO_NAME}-flb-sc-config-map" + - name: business-data + persistentVolumeClaim: + claimName: business-data test: false - apiVersion: v1 kind: Service @@ -154,8 +159,18 @@ objects: resource: name: memory target: - averageUtilization: 200 + averageUtilization: 250 type: Utilization + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: business-data + spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: ${{STORAGE_LIMIT}} parameters: - name: REPO_NAME description: Application repository name @@ -196,3 +211,6 @@ parameters: - name: MAX_MEM description: The maximum amount of memory required: true + - name: STORAGE_LIMIT + description: Max storage + required: true