From c94e91ec66eecda17083082afa03a246b1ff6d85 Mon Sep 17 00:00:00 2001
From: Thomas Kammerlocher
Date: Mon, 27 May 2024 11:12:52 +0200
Subject: [PATCH] feat: added Health Endpoint returning sync status. (#16)
* feat: added Health Endpoint returning sync status.
* feat: added sync status dto. Sync status will be true if the syncjob won't start and will signalize it with a different status message.
* feat: added sync status dto. Sync status will be true if the syncjob won't start and will signalize it with a different status message.
---
.../registry/api/controller/HealthApi.java | 24 +++++++++++++
.../api/controller/HealthApiController.java | 31 +++++++++++++++++
.../api/model/rest/HealthResponse.java | 25 ++++++++++++++
api/src/main/resources/api.yaml | 20 +++++++++++
.../registry/model/enums/SyncStatusEnum.java | 23 +++++++++++++
.../registry/service/SyncStatus.java | 14 ++++++++
.../service/TokenMetadataSyncService.java | 34 +++++++++++++++----
.../registry/util/Constants.java | 13 +++++++
8 files changed, 178 insertions(+), 6 deletions(-)
create mode 100644 api/src/main/java/org/cardanofoundation/tokenmetadata/registry/api/controller/HealthApi.java
create mode 100644 api/src/main/java/org/cardanofoundation/tokenmetadata/registry/api/controller/HealthApiController.java
create mode 100644 api/src/main/java/org/cardanofoundation/tokenmetadata/registry/api/model/rest/HealthResponse.java
create mode 100644 common/src/main/java/org/cardanofoundation/tokenmetadata/registry/model/enums/SyncStatusEnum.java
create mode 100644 common/src/main/java/org/cardanofoundation/tokenmetadata/registry/service/SyncStatus.java
create mode 100644 common/src/main/java/org/cardanofoundation/tokenmetadata/registry/util/Constants.java
diff --git a/api/src/main/java/org/cardanofoundation/tokenmetadata/registry/api/controller/HealthApi.java b/api/src/main/java/org/cardanofoundation/tokenmetadata/registry/api/controller/HealthApi.java
new file mode 100644
index 0000000..0823732
--- /dev/null
+++ b/api/src/main/java/org/cardanofoundation/tokenmetadata/registry/api/controller/HealthApi.java
@@ -0,0 +1,24 @@
+package org.cardanofoundation.tokenmetadata.registry.api.controller;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.cardanofoundation.tokenmetadata.registry.api.model.rest.HealthResponse;
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+@Validated
+@Tag(name = "health", description = "Health Endpoint for the cardano token metadata registry")
+public interface HealthApi {
+
+ @Operation(operationId = "getHealthStatus", summary = "Returns health status of service including if the initial sync is done", responses = {
+ @ApiResponse(responseCode = "200", content = @Content(mediaType = "application/json", schema = @Schema(implementation = HealthResponse.class)))
+ })
+ @RequestMapping(method = RequestMethod.GET, value = "/health", produces = {"application/json;charset=utf-8"})
+ ResponseEntity getHealthStatus();
+
+}
diff --git a/api/src/main/java/org/cardanofoundation/tokenmetadata/registry/api/controller/HealthApiController.java b/api/src/main/java/org/cardanofoundation/tokenmetadata/registry/api/controller/HealthApiController.java
new file mode 100644
index 0000000..08ef470
--- /dev/null
+++ b/api/src/main/java/org/cardanofoundation/tokenmetadata/registry/api/controller/HealthApiController.java
@@ -0,0 +1,31 @@
+package org.cardanofoundation.tokenmetadata.registry.api.controller;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.cardanofoundation.tokenmetadata.registry.api.model.rest.HealthResponse;
+import org.cardanofoundation.tokenmetadata.registry.service.SyncStatus;
+import org.cardanofoundation.tokenmetadata.registry.service.TokenMetadataSyncService;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@Controller
+@CrossOrigin
+@RequestMapping("${openapi.metadataServer.base-path:}")
+@Slf4j
+@RequiredArgsConstructor
+public class HealthApiController implements HealthApi {
+
+ private final TokenMetadataSyncService tokenMetadataSyncService;
+
+ @Override
+ public ResponseEntity getHealthStatus() {
+ SyncStatus syncStatus = tokenMetadataSyncService.getSyncStatus();
+ return new ResponseEntity<>(HealthResponse.builder()
+ .synced(syncStatus.isInitialSyncDone())
+ .syncStatus(syncStatus.getSyncStatus().toString())
+ .build(), HttpStatus.OK);
+ }
+}
diff --git a/api/src/main/java/org/cardanofoundation/tokenmetadata/registry/api/model/rest/HealthResponse.java b/api/src/main/java/org/cardanofoundation/tokenmetadata/registry/api/model/rest/HealthResponse.java
new file mode 100644
index 0000000..ad16ae5
--- /dev/null
+++ b/api/src/main/java/org/cardanofoundation/tokenmetadata/registry/api/model/rest/HealthResponse.java
@@ -0,0 +1,25 @@
+package org.cardanofoundation.tokenmetadata.registry.api.model.rest;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import jakarta.validation.Valid;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.cardanofoundation.tokenmetadata.registry.model.enums.SyncStatusEnum;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class HealthResponse {
+
+ @JsonProperty("synced")
+ @Valid
+ private boolean synced;
+
+ @JsonProperty("syncStatus")
+ @Valid
+ private String syncStatus;
+
+}
diff --git a/api/src/main/resources/api.yaml b/api/src/main/resources/api.yaml
index 9c28e1e..9516bac 100644
--- a/api/src/main/resources/api.yaml
+++ b/api/src/main/resources/api.yaml
@@ -18,6 +18,19 @@ x-tagGroups:
- v1 queries
- v2 queries
paths:
+ /health:
+ get:
+ summary: "Get Health status"
+ tags:
+ - v1 queries
+ operationId: "health"
+ responses:
+ 200:
+ description: "Health Response including if initial sync is done and current syncing status."
+ content:
+ application/json;charset=utf-8:
+ schema:
+ $ref: '#/components/schemas/HealthResponse'
/metadata/{subject}:
get:
summary: "Query All Properties"
@@ -545,6 +558,13 @@ components:
type: array
items:
$ref: '#/components/schemas/Property'
+ HealthResponse:
+ type: object
+ properties:
+ synced:
+ type: boolean
+ syncStatus:
+ type: string
BatchRequest:
required:
- subjects
diff --git a/common/src/main/java/org/cardanofoundation/tokenmetadata/registry/model/enums/SyncStatusEnum.java b/common/src/main/java/org/cardanofoundation/tokenmetadata/registry/model/enums/SyncStatusEnum.java
new file mode 100644
index 0000000..b2a4d62
--- /dev/null
+++ b/common/src/main/java/org/cardanofoundation/tokenmetadata/registry/model/enums/SyncStatusEnum.java
@@ -0,0 +1,23 @@
+package org.cardanofoundation.tokenmetadata.registry.model.enums;
+
+import org.cardanofoundation.tokenmetadata.registry.util.Constants;
+
+public enum SyncStatusEnum {
+
+ SYNC_NOT_STARTED(Constants.SYNC_NOT_STARTED),
+ SYNC_IN_PROGRESS(Constants.SYNC_IN_PROGRESS),
+ SYNC_DONE(Constants.SYNC_DONE),
+ SYNC_ERROR(Constants.SYNC_ERROR),
+ SYNC_IN_EXTRA_JOB(Constants.SYNC_IN_EXTRA_JOB);
+
+ private final String text;
+
+ SyncStatusEnum(final String text) {
+ this.text = text;
+ }
+
+ @Override
+ public String toString() {
+ return text;
+ }
+}
diff --git a/common/src/main/java/org/cardanofoundation/tokenmetadata/registry/service/SyncStatus.java b/common/src/main/java/org/cardanofoundation/tokenmetadata/registry/service/SyncStatus.java
new file mode 100644
index 0000000..dfd3744
--- /dev/null
+++ b/common/src/main/java/org/cardanofoundation/tokenmetadata/registry/service/SyncStatus.java
@@ -0,0 +1,14 @@
+package org.cardanofoundation.tokenmetadata.registry.service;
+
+import lombok.Builder;
+import lombok.Data;
+import org.cardanofoundation.tokenmetadata.registry.model.enums.SyncStatusEnum;
+
+@Builder
+@Data
+public class SyncStatus {
+
+ private boolean isInitialSyncDone;
+ private SyncStatusEnum syncStatus;
+
+}
diff --git a/common/src/main/java/org/cardanofoundation/tokenmetadata/registry/service/TokenMetadataSyncService.java b/common/src/main/java/org/cardanofoundation/tokenmetadata/registry/service/TokenMetadataSyncService.java
index 4c4dee4..c467202 100644
--- a/common/src/main/java/org/cardanofoundation/tokenmetadata/registry/service/TokenMetadataSyncService.java
+++ b/common/src/main/java/org/cardanofoundation/tokenmetadata/registry/service/TokenMetadataSyncService.java
@@ -1,10 +1,14 @@
package org.cardanofoundation.tokenmetadata.registry.service;
-import lombok.AllArgsConstructor;
+import jakarta.annotation.PostConstruct;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.cardanofoundation.tokenmetadata.registry.model.Mapping;
import org.cardanofoundation.tokenmetadata.registry.model.MappingDetails;
import org.cardanofoundation.tokenmetadata.registry.model.MappingUpdateDetails;
+import org.cardanofoundation.tokenmetadata.registry.model.enums.SyncStatusEnum;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.File;
@@ -12,15 +16,11 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Optional;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.stream.Collectors;
import java.util.stream.Stream;
-import static java.util.stream.Collectors.groupingBy;
-
@Service
@Slf4j
-@AllArgsConstructor
+@RequiredArgsConstructor
public class TokenMetadataSyncService {
private final GitService gitService;
@@ -29,8 +29,25 @@ public class TokenMetadataSyncService {
private final TokenMappingService tokenMappingService;
+ @Value("${token.metadata.job.enabled}")
+ private boolean isMetadataJobEnabled;
+
+ @Getter
+ private SyncStatus syncStatus;
+
+ @PostConstruct
+ private void initSyncStatus() {
+ if(isMetadataJobEnabled) {
+ syncStatus = new SyncStatus(false, SyncStatusEnum.SYNC_NOT_STARTED);
+ } else {
+ syncStatus = new SyncStatus(true, SyncStatusEnum.SYNC_IN_EXTRA_JOB);
+ }
+ }
+
public void synchronizeDatabase() {
+ syncStatus.setSyncStatus(SyncStatusEnum.SYNC_IN_PROGRESS);
+
Optional repoPathOpt = gitService.cloneCardanoTokenRegistryGitRepository();
if (repoPathOpt.isPresent()) {
@@ -64,10 +81,15 @@ public void synchronizeDatabase() {
});
+ syncStatus.setSyncStatus(SyncStatusEnum.SYNC_DONE);
+ syncStatus.setInitialSyncDone(true);
+
} else {
log.warn("cardano-token-registry could not be cloned");
+ syncStatus.setSyncStatus(SyncStatusEnum.SYNC_ERROR);
}
}
+
}
diff --git a/common/src/main/java/org/cardanofoundation/tokenmetadata/registry/util/Constants.java b/common/src/main/java/org/cardanofoundation/tokenmetadata/registry/util/Constants.java
new file mode 100644
index 0000000..a8ff080
--- /dev/null
+++ b/common/src/main/java/org/cardanofoundation/tokenmetadata/registry/util/Constants.java
@@ -0,0 +1,13 @@
+package org.cardanofoundation.tokenmetadata.registry.util;
+
+public class Constants {
+
+ private Constants() {}
+
+ public static String SYNC_NOT_STARTED = "Sync not started";
+ public static String SYNC_IN_PROGRESS = "Sync in progress";
+ public static String SYNC_DONE = "Sync done";
+ public static String SYNC_ERROR = "Error while syncing";
+ public static String SYNC_IN_EXTRA_JOB = "Sync will be done in a different job. Status unkown";
+
+}