Added async loading for document uploading to external system.
This commit is contained in:
@@ -5,9 +5,11 @@ import com.amazonaws.services.s3.model.GetObjectRequest;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import feign.FeignException;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.gepafin.tendermanagement.config.Translator;
|
||||
import net.gepafin.tendermanagement.config.jwt.TokenProvider;
|
||||
import net.gepafin.tendermanagement.constants.AppointmentApiConstant;
|
||||
import net.gepafin.tendermanagement.constants.GepafinConstant;
|
||||
import net.gepafin.tendermanagement.entities.ApplicationEntity;
|
||||
@@ -125,8 +127,15 @@ public class AppointmentDao {
|
||||
@Autowired
|
||||
private LoggingUtil loggingUtil;
|
||||
|
||||
@Autowired
|
||||
private TokenProvider tokenProvider;
|
||||
|
||||
private final Map<Long, ExecutorService> executorMap = new ConcurrentHashMap<>();
|
||||
|
||||
private final ConcurrentHashMap<Long, ExecutorService> threadForDocumentMap = new ConcurrentHashMap<>();
|
||||
|
||||
private static final ThreadLocal<Long> threadLocalHubId = new ThreadLocal<>();
|
||||
|
||||
public NdgResponse checkNdgForAppointment(Long applicationId) {
|
||||
|
||||
ApplicationEntity application = applicationService.validateApplication(applicationId);
|
||||
@@ -719,87 +728,101 @@ public class AppointmentDao {
|
||||
return appointmentCreationRequest;
|
||||
}
|
||||
|
||||
public DocumentUploadResponse uploadDocumentToExternalSystem(Long documentId, UploadDocToExternalSystemRequest docToExternalSystemRequest, Long applicationId) {
|
||||
|
||||
DocumentUploadResponse response = new DocumentUploadResponse();
|
||||
public DocumentUploadResponse uploadDocumentToExternalSystem(Long documentId, UploadDocToExternalSystemRequest docToExternalSystemRequest) {
|
||||
// Check if the document is already being processed
|
||||
DocumentEntity systemDoc = documentDao.validateDocument(documentId);
|
||||
|
||||
ApplicationEntity application = getApplicationEntityForDocument(applicationId, systemDoc);
|
||||
|
||||
//cloned for old document data
|
||||
DocumentEntity oldDocumentEntity = Utils.getClonedEntityForData(systemDoc);
|
||||
|
||||
if (!docToExternalSystemRequest.getInput().getAttributes().getNdg().equalsIgnoreCase(application.getNdg())) {
|
||||
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.NDG_NOT_MATCHED_OR_NOT_FOUND));
|
||||
Claims claims = tokenProvider.getClaimsFromToken(tokenProvider.extractTokenFromRequest(request));
|
||||
Long hubId = Utils.extractHubIdFromPayload(claims.getSubject());
|
||||
if (systemDoc.getDocumentAttachmentId() != null) {
|
||||
// If the documentAttachmentId is already set, return the response
|
||||
log.info("Document already uploaded with documentAttachmentId: {}", systemDoc.getDocumentAttachmentId());
|
||||
DocumentUploadResponse response = new DocumentUploadResponse();
|
||||
response.setDocumentAttachmentId(systemDoc.getDocumentAttachmentId());
|
||||
return response;
|
||||
}
|
||||
// Check if a thread is already running for this document upload
|
||||
if (threadForDocumentMap.containsKey(documentId)) {
|
||||
log.warn("Document upload already running for documentId: {}", documentId);
|
||||
throw new CustomValidationException(Status.SUCCESS, Translator.toLocale(GepafinConstant.DOCUMENT_UPLOADING_IN_PROGRESS));
|
||||
}
|
||||
// Start the upload process in the background
|
||||
ExecutorService executor = Executors.newSingleThreadExecutor(runnable -> {
|
||||
Thread thread = new Thread(runnable);
|
||||
thread.setName(GepafinConstant.ASYNC_DOCUMENT_UPLOAD_NAME + documentId);
|
||||
return thread;
|
||||
});
|
||||
threadForDocumentMap.put(documentId, executor);
|
||||
|
||||
Long hubId = application.getHubId();
|
||||
executor.submit(() -> {
|
||||
threadLocalHubId.set(hubId);
|
||||
try {
|
||||
log.info("Starting async document upload for documentId: {}", documentId);
|
||||
uploadDocumentToExternalSystemSync(documentId, docToExternalSystemRequest);
|
||||
} catch (Exception e) {
|
||||
log.error("Error in async document upload for documentId: {}", documentId, e);
|
||||
} finally {
|
||||
// Cleanup resources
|
||||
ExecutorService executorToShutdown = threadForDocumentMap.remove(documentId);
|
||||
if (executorToShutdown != null) {
|
||||
executorToShutdown.shutdown();
|
||||
threadLocalHubId.remove();
|
||||
}
|
||||
log.info("Async document upload completed for documentId: {}", documentId);
|
||||
}
|
||||
});
|
||||
// Return an immediate response indicating the process is in progress
|
||||
throw new CustomValidationException(Status.SUCCESS, Translator.toLocale(GepafinConstant.DOCUMENT_UPLOADING_IN_PROGRESS));
|
||||
}
|
||||
|
||||
private void uploadDocumentToExternalSystemSync(Long documentId, UploadDocToExternalSystemRequest docToExternalSystemRequest) {
|
||||
// Synchronous upload logic
|
||||
DocumentEntity systemDoc = documentDao.validateDocument(documentId);
|
||||
|
||||
Long hubId = threadLocalHubId.get();
|
||||
HubEntity hub = hubRepository.findByHubId(hubId);
|
||||
|
||||
if (!hub.getUniqueUuid().equals(defaultHubUuid)) {
|
||||
log.info("Document cannot be uploaded for another Hub, it is default for Gepafin.");
|
||||
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.NO_DOCUMENT_UPLOAD_FOR_ANOTHER_HUB));
|
||||
}
|
||||
log.info("Got Document in system {}", systemDoc);
|
||||
|
||||
log.info("Got Document in system: {}", systemDoc);
|
||||
String oldUrl = systemDoc.getFilePath();
|
||||
log.info("Processing {}", oldUrl);
|
||||
|
||||
String authorizationToken = getBearerToken(hub);
|
||||
|
||||
try {
|
||||
File localFile = downloadFileFromS3(oldUrl);
|
||||
MultipartFile multipartFile = convertFileToMultipartFile(localFile);
|
||||
|
||||
UploadDocToExternalSystemRequest externalSystemRequest = new UploadDocToExternalSystemRequest();
|
||||
|
||||
UploadDocToExternalSystemRequest.Input input = getUploadDocumentInput(docToExternalSystemRequest);
|
||||
externalSystemRequest.setInput(input);
|
||||
externalSystemRequest.setInput(getUploadDocumentInput(docToExternalSystemRequest));
|
||||
|
||||
String uploadDocRequest = Utils.convertObjectToJson(externalSystemRequest);
|
||||
ResponseEntity<Object> uploadedDocumentData = appointmentApiService.uploadDocumentToExternalSystemForAppointment(authorizationToken, context, uploadDocRequest,
|
||||
multipartFile);
|
||||
String responseData = Utils.convertObjectToJson(uploadedDocumentData.getBody());
|
||||
DocumentUploadResponse parsedDocumentUploadResponse = parseDocumentUploadResponse(responseData);
|
||||
|
||||
if (parsedDocumentUploadResponse == null) {
|
||||
String responseData = Utils.convertObjectToJson(uploadedDocumentData.getBody());
|
||||
DocumentUploadResponse parsedResponse = parseDocumentUploadResponse(responseData);
|
||||
|
||||
if (parsedResponse == null) {
|
||||
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.ERROR_UPLOADING_DOCUMENT));
|
||||
}
|
||||
|
||||
systemDoc.setDocumentAttachmentId(parsedDocumentUploadResponse.getDocumentAttachmentId());
|
||||
// Save the documentAttachmentId to the database
|
||||
systemDoc.setDocumentAttachmentId(parsedResponse.getDocumentAttachmentId());
|
||||
documentRepository.save(systemDoc);
|
||||
|
||||
/** This code is responsible for adding a version history log for the "Update document with document attachment id" operation. **/
|
||||
loggingUtil.addVersionHistory(
|
||||
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldDocumentEntity).newData(systemDoc).build());
|
||||
|
||||
log.info("Document uploaded successfully to external system : {}", parsedDocumentUploadResponse);
|
||||
response.setDocumentAttachmentId(systemDoc.getDocumentAttachmentId());
|
||||
return response;
|
||||
log.info("Document uploaded successfully to external system: {}", parsedResponse);
|
||||
} catch (FeignException.Forbidden forbiddenException) {
|
||||
log.error("403 Forbidden received while uploading document to external system. Regenerating token...");
|
||||
|
||||
log.error("403 Forbidden received while uploading document. Regenerating token...");
|
||||
regenerateTokenAndSave(hub);
|
||||
return uploadDocumentToExternalSystem(systemDoc.getSourceId(), docToExternalSystemRequest, applicationId);
|
||||
uploadDocumentToExternalSystemSync(documentId, docToExternalSystemRequest);
|
||||
} catch (Exception e) {
|
||||
log.error("Exception in uploading document to external system {}", e.getMessage());
|
||||
log.error("Exception during document upload: {}", e.getMessage(), e);
|
||||
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.EXTERNAL_DOCUMENT_UPLOAD_FAILURE_MSG));
|
||||
}
|
||||
}
|
||||
private ApplicationEntity getApplicationEntityForDocument(Long applicationId, DocumentEntity systemDoc) {
|
||||
|
||||
if (systemDoc.getDocumentAttachmentId() != null) {
|
||||
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.DOCUMENT_ALREADY_UPLOADED));
|
||||
}
|
||||
|
||||
ApplicationEntity application;
|
||||
|
||||
if (systemDoc.getSource().equalsIgnoreCase(DocumentSourceTypeEnum.APPLICATION.getValue()) && Objects.equals(systemDoc.getSourceId(), applicationId)) {
|
||||
application = applicationService.validateApplication(systemDoc.getSourceId());
|
||||
} else {
|
||||
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.PROVIDE_VALID_APPLICATION_DOC_ID));
|
||||
}
|
||||
return application;
|
||||
}
|
||||
|
||||
private UploadDocToExternalSystemRequest.Input getUploadDocumentInput(UploadDocToExternalSystemRequest docToExternalSystemRequest) {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user