Skip to content

Commit

Permalink
Merge pull request #261 from holashchand/id-gen-service
Browse files Browse the repository at this point in the history
Id gen service integration
  • Loading branch information
srprasanna authored Nov 6, 2023
2 parents 44199e4 + 577052b commit 3ca3d41
Show file tree
Hide file tree
Showing 117 changed files with 3,014 additions and 10 deletions.
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ IMAGES := ghcr.io/sunbird-rc/sunbird-rc-core ghcr.io/sunbird-rc/sunbird-rc-nginx
ghcr.io/sunbird-rc/sunbird-rc-public-key-service ghcr.io/sunbird-rc/sunbird-rc-keycloak ghcr.io/sunbird-rc/sunbird-rc-certificate-api \
ghcr.io/sunbird-rc/sunbird-rc-certificate-signer ghcr.io/sunbird-rc/sunbird-rc-notification-service ghcr.io/sunbird-rc/sunbird-rc-claim-ms \
ghcr.io/sunbird-rc/sunbird-rc-digilocker-certificate-api ghcr.io/sunbird-rc/sunbird-rc-bulk-issuance ghcr.io/sunbird-rc/sunbird-rc-metrics \
ghcr.io/sunbird-rc/encryption-service
ghcr.io/sunbird-rc/id-gen-service ghcr.io/sunbird-rc/encryption-service
build: java/registry/target/registry.jar
echo ${SOURCES}
rm -rf java/claim/target/*.jar
Expand All @@ -21,6 +21,7 @@ build: java/registry/target/registry.jar
make -C services/metrics docker
make -C services/digilocker-certificate-api docker
make -C services/bulk_issuance docker
make -C services/id-gen-service docker
make -C services/encryption-service docker
docker build -t ghcr.io/sunbird-rc/sunbird-rc-nginx .

Expand Down
14 changes: 13 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -352,8 +352,19 @@ services:
test:
wget --no-verbose --tries=1 --spider http://localhost:8123/ping || exit
1
id-gen-service:
image: ghcr.io/sunbird-rc/id-gen-service:${RELEASE_VERSION}
ports:
- '8088:8088'
environment:
spring.datasource.url: jdbc:postgresql://db:5432/registry
spring.flyway.baseline-on-migrate: "true"
egov.mdms.provider: org.egov.id.masterdata.provider.DBMasterDataProvider
depends_on:
db:
condition: service_healthy
encryption-service:
image: ghcr.io/sunbird-rc/encryption-service
image: ghcr.io/sunbird-rc/encryption-service:${RELEASE_VERSION}
ports:
- '8013:8013'
environment:
Expand All @@ -362,6 +373,7 @@ services:
spring.datasource.url: jdbc:postgresql://db:5432/registry
spring.flyway.url: jdbc:postgresql://db:5432/registry
egov.mdms.provider: org.egov.enc.masterdata.provider.DBMasterDataProvider
spring.flyway.baseline-on-migrate: "true"
depends_on:
db:
condition: service_healthy
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class Constants {

public static final String SUNBIRDRC_REGISTRY_API = "sunbirdrc-registry-api"; //todo make it configurable for backward compatibility
public static final String SUNBIRD_ENCRYPTION_SERVICE_NAME = "sunbird.encryption.service";
public static final String SUNBIRD_ID_GEN_SERVICE_NAME = "sunbird.idgen.service";
public static final String SUNBIRD_SIGNATURE_SERVICE_NAME = "sunbird.signature.service";

public static final String SUNBIRD_ELASTIC_SERVICE_NAME = "sunbird.elastic.service";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package dev.sunbirdrc.pojos;

import lombok.*;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
public class UniqueIdentifierField {
String field;
String idName;
String format;
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ public void run(ApplicationArguments args) throws Exception {
entityParenter.ensureKnownParenters();
entityParenter.loadDefinitionIndex();
entityParenter.ensureIndexExists();
entityParenter.saveIdFormat();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package dev.sunbirdrc.registry.exception;

public class UniqueIdentifierException extends Exception{


private static final long serialVersionUID = -6315798195661762883L;

public UniqueIdentifierException(CustomException e) {
super(e);
}

public class CreationException extends CustomException {
private static final long serialVersionUID = 6174717850058203377L;

public CreationException(String msg) {
super("Unable to create unique ID: " + msg);
}
}

public static class UnreachableException extends CustomException {

private static final long serialVersionUID = 5384120386096139086L;

public UnreachableException(String message) {
super("Unable to reach id-gen service: " + message);
}
}

public static class GenerateException extends CustomException {

private static final long serialVersionUID = 8311355815972497247L;

public GenerateException(String message) {
super("Unable to generate id: " + message);
}
}

public static class IdFormatException extends CustomException {

private static final long serialVersionUID = 8311355815972497248L;

public IdFormatException(String message) {
super("Unable to save UniqueIdentifierField format: " + message);
}
}

public static class FieldConfigNotFoundException extends CustomException {

private static final long serialVersionUID = 8311355815972497249L;

public FieldConfigNotFoundException(String message) {
super("Unable to find UniqueIdentifierField configuration in schema configuration: " + message);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package dev.sunbirdrc.registry.service;

import dev.sunbirdrc.pojos.HealthIndicator;
import dev.sunbirdrc.pojos.UniqueIdentifierField;
import dev.sunbirdrc.registry.exception.CustomException;

import java.util.List;
import java.util.Map;

public interface IIdGenService extends HealthIndicator {

Map<String, String> generateId(List<UniqueIdentifierField> uniqueIdentifierFields) throws CustomException;

void saveIdFormat(List<UniqueIdentifierField> uniqueIdentifierFields) throws CustomException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,21 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import dev.sunbirdrc.pojos.UniqueIdentifierField;
import dev.sunbirdrc.registry.entities.SchemaStatus;
import dev.sunbirdrc.registry.exception.CustomException;
import dev.sunbirdrc.registry.exception.SchemaException;
import dev.sunbirdrc.registry.middleware.util.JSONUtil;
import dev.sunbirdrc.registry.util.Definition;
import dev.sunbirdrc.registry.util.IDefinitionsManager;
import dev.sunbirdrc.validators.IValidate;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.List;

import static dev.sunbirdrc.registry.Constants.PATH;
import static dev.sunbirdrc.registry.Constants.Schema;
Expand All @@ -27,6 +31,11 @@ public class SchemaService {
@Autowired
private IDefinitionsManager definitionsManager;

@Autowired(required = false)
private IIdGenService idGenService;
@Value("${idgen.enabled:false}")
private boolean idGenEnabled;

@Autowired
private boolean isElasticSearchEnabled;

Expand Down Expand Up @@ -56,15 +65,18 @@ public void addSchema(JsonNode schemaNode) throws IOException, SchemaException {
} else {
throw new SchemaException("Duplicate Error: Schema already exists");
}
saveIdFormat(definition.getTitle());
}
}

public void updateSchema(JsonNode updatedSchema) throws IOException {
public void updateSchema(JsonNode updatedSchema) throws IOException, SchemaException {
JsonNode schemaNode = updatedSchema.get(Schema);
if (schemaNode.get(STATUS) != null && schemaNode.get(STATUS).textValue().equals(SchemaStatus.PUBLISHED.toString())) {
JsonNode schema = schemaNode.get(Schema.toLowerCase());
Definition definition = Definition.toDefinition(schema);
definitionsManager.appendNewDefinition(schema);
validator.addDefinitions(schema);
saveIdFormat(definition.getTitle());
}
}

Expand Down Expand Up @@ -123,5 +135,15 @@ public void validateUpdateSchema(JsonNode existingSchemaNode, JsonNode updatedSc
}
}

private void saveIdFormat(String title) throws SchemaException {
if(!idGenEnabled) return;
List<UniqueIdentifierField> identifierFieldList = definitionsManager.getUniqueIdentifierFields(title);
try {
idGenService.saveIdFormat(identifierFieldList);
} catch (CustomException e) {
throw new SchemaException(e.getMessage(), e.getCause());
}
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
package dev.sunbirdrc.registry.service.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.google.gson.Gson;
import dev.sunbirdrc.pojos.ComponentHealthInfo;
import dev.sunbirdrc.pojos.SunbirdRCInstrumentation;
import dev.sunbirdrc.pojos.UniqueIdentifierField;
import dev.sunbirdrc.registry.exception.CustomException;
import dev.sunbirdrc.registry.exception.UniqueIdentifierException.*;
import dev.sunbirdrc.registry.middleware.util.JSONUtil;
import dev.sunbirdrc.registry.service.IIdGenService;
import dev.sunbirdrc.registry.util.IDefinitionsManager;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestClientException;

import java.util.*;
import java.util.stream.Collectors;

import static dev.sunbirdrc.registry.middleware.util.Constants.CONNECTION_FAILURE;
import static dev.sunbirdrc.registry.middleware.util.Constants.SUNBIRD_ID_GEN_SERVICE_NAME;

@Service
@ConditionalOnProperty(name = "idgen.enabled", havingValue = "true")
public class IdGenService implements IIdGenService {
private static final Logger logger = LoggerFactory.getLogger(IdGenService.class);

@Value("${idgen.generateURL}")
private String generateUrl;
@Value("${idgen.idFormatURL}")
private String idFormatUrl;
@Value("${idgen.healthCheckURL}")
private String healthCheckUrl;
@Value("${idgen.tenantId}")
private String tenantId;
@Value("${idgen.enabled:false}")
private boolean enabled;

@Autowired
private Gson gson;
@Autowired
private SunbirdRCInstrumentation watch;
@Autowired
private RetryRestTemplate retryRestTemplate;

@Override
public Map<String, String> generateId(List<UniqueIdentifierField> uniqueIdentifierFields) throws CustomException {
if(!enabled) throw new UnreachableException("IDGEN service not enabled");
HttpEntity<String> entity = getIdgenRequest(uniqueIdentifierFields);

try {
watch.start("IdGenServiceImpl.generateId");
ResponseEntity<String> response = retryRestTemplate.postForEntity(generateUrl, entity);
watch.stop("IdGenServiceImpl.generateId");
JsonNode results = JSONUtil.convertStringJsonNode(response.getBody());
if("SUCCESSFUL".equals(results.at("/responseInfo/status").asText())) {
logger.info("Generated value successfully");
Map<String, String> resultMap = new HashMap<>();
Iterator<JsonNode> iterator = ((ArrayNode) results.at("/idResponses")).elements();
int i = 0;
while(iterator.hasNext()) {
resultMap.put(uniqueIdentifierFields.get(i).getField(), iterator.next().at("/id").asText());
i++;
}
return resultMap;
}
throw new GenerateException(results.at("/idResponses").asText());
} catch (ResourceAccessException e) {
logger.error("Exception while connecting {} : {}", getServiceName(), ExceptionUtils.getStackTrace(e));
throw new UnreachableException("Exception while connecting idgen service ! ");
} catch (Exception e) {
logger.error("Exception in {}: {}", getServiceName(), ExceptionUtils.getStackTrace(e));
throw new GenerateException("Exception occurred while generating id");
}
}

@Override
public void saveIdFormat(List<UniqueIdentifierField> uniqueIdentifierFields) throws CustomException {
if(!enabled) throw new UnreachableException("IDGEN service not enabled");
HttpEntity<String> entity = getIdgenRequest(uniqueIdentifierFields);

try {
watch.start("IdGenServiceImpl.saveFormat");
ResponseEntity<String> response = retryRestTemplate.postForEntity(idFormatUrl, entity);
watch.stop("IdGenServiceImpl.saveFormat");
JsonNode results = JSONUtil.convertStringJsonNode(response.getBody());
if(!"SUCCESSFUL".equals(results.at("/responseInfo/status").asText())) {
Iterator<JsonNode> iterator = ((ArrayNode) results.at("/errorMsgs")).elements();
while(iterator.hasNext()) {
JsonNode node = iterator.next();
if (node.isNull()) continue;
if (!node.asText().contains("already exists")) {
throw new IdFormatException(node.asText());
}
}
}
} catch (ResourceAccessException e) {
logger.error("Exception while connecting {} : {}", getServiceName(), ExceptionUtils.getStackTrace(e));
throw new UnreachableException("Exception while connecting idgen service ! ");
} catch (Exception e) {
logger.error("Exception in {}: {}", getServiceName(), ExceptionUtils.getStackTrace(e));
throw new GenerateException("Exception occurred while generating id");
}
}

private HttpEntity<String> getIdgenRequest(List<UniqueIdentifierField> uniqueIdentifierFields) {
Map<String, Object> map = new HashMap<>();
map.put("RequestInfo", new HashMap<>());
List<Map<String, String>> idRequests = uniqueIdentifierFields.stream().map(field -> {
Map<String, String> idRequest = new HashMap<>();
idRequest.put("idName", field.getIdName());
idRequest.put("tenantId", tenantId);
idRequest.put("format", field.getFormat());
return idRequest;
}).collect(Collectors.toList());

map.put("idRequests", idRequests);

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return new HttpEntity<>(gson.toJson(map), headers);
}

@Override
public String getServiceName() {
return SUNBIRD_ID_GEN_SERVICE_NAME;
}

@Override
public ComponentHealthInfo getHealthInfo() {
if (enabled) {
try {
ResponseEntity<String> response = retryRestTemplate.getForEntity(healthCheckUrl);
if (!StringUtils.isEmpty(response.getBody()) && response.getBody().equalsIgnoreCase("UP")) {
logger.debug(" running !");
return new ComponentHealthInfo(getServiceName(), true);
} else {
return new ComponentHealthInfo(getServiceName(), false, CONNECTION_FAILURE, response.getBody());
}
} catch (RestClientException ex) {
logger.error("RestClientException when checking the health of the idgen service: {}", ExceptionUtils.getStackTrace(ex));
return new ComponentHealthInfo(getServiceName(), false, CONNECTION_FAILURE, ex.getMessage());
}
} else {
return new ComponentHealthInfo(getServiceName(), true, "IDGEN_ENABLED", "false");
}
}
}
Loading

0 comments on commit 3ca3d41

Please sign in to comment.