Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Id gen service integration #261

Merged
merged 5 commits into from
Nov 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading