Skip to content

Commit

Permalink
Grad Release 1.6.0
Browse files Browse the repository at this point in the history
Grad Release 1.6.0
  • Loading branch information
kamal-mohammed authored Sep 19, 2023
2 parents e4c1af4 + 8ccd543 commit c57e3bb
Show file tree
Hide file tree
Showing 12 changed files with 223 additions and 40 deletions.
2 changes: 1 addition & 1 deletion api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>ca.bc.gov.educ</groupId>
<artifactId>educ-grad-student-api</artifactId>
<version>1.8.46</version>
<version>1.8.47</version>
<name>educ-grad-student-api</name>
<description>Student Demographics API for GRAD team</description>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ public enum Topics {
* GradStatus events topic.
*/
GRAD_STATUS_EVENT_TOPIC,
FETCH_GRAD_STATUS
GRAD_STUDENT_API_FETCH_GRAD_STATUS_TOPIC
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package ca.bc.gov.educ.api.gradstudent.messaging.jetstream;

import ca.bc.gov.educ.api.gradstudent.constant.Topics;
import ca.bc.gov.educ.api.gradstudent.exception.EntityNotFoundException;
import ca.bc.gov.educ.api.gradstudent.model.dc.Event;
import ca.bc.gov.educ.api.gradstudent.model.dto.ChoreographedEvent;
import ca.bc.gov.educ.api.gradstudent.service.GraduationStatusService;
import ca.bc.gov.educ.api.gradstudent.util.EducGradStudentApiConstants;
import ca.bc.gov.educ.api.gradstudent.util.JsonUtil;
Expand All @@ -23,7 +23,7 @@ public class FetchGradStatusSubscriber implements MessageHandler {
private final GraduationStatusService graduationStatusService;

private final EducGradStudentApiConstants constants;
private static final String TOPIC = "FETCH_GRAD_STATUS";
private static final String TOPIC = Topics.GRAD_STUDENT_API_FETCH_GRAD_STATUS_TOPIC.toString();

@Autowired
public FetchGradStatusSubscriber(final Connection natsConnection, GraduationStatusService graduationStatusService, EducGradStudentApiConstants constants) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package ca.bc.gov.educ.api.gradstudent.model.dto;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class GradTraxStudent {
private String pen;
private String program; // inc
private Date programCompletionDate; // inc
private String slpDate; // inc
private String sccDate;
private String gpa;
private String honoursStanding; // inc
private String studentGradData;
private String schoolOfRecord; // inc
private String schoolAtGrad; // inc
private String studentGrade; // inc
private String studentStatus; // inc
private String archiveFlag; // inc
private String frenchCert;
private String englishCert;
private String frenchDogwood;
private String consumerEducationRequirementMet;
private String studentCitizenship;

// extra
private String graduationRequirementYear;

// grad or non-grad
private Date distributionDate;
private String transcriptSchoolCategoryCode;
private String certificateSchoolCategoryCode;
// 1950 "AD"
private boolean adult19Rule;
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package ca.bc.gov.educ.api.gradstudent.scheduler;

import ca.bc.gov.educ.api.gradstudent.messaging.jetstream.Publisher;
import ca.bc.gov.educ.api.gradstudent.model.entity.GradStatusEvent;
import ca.bc.gov.educ.api.gradstudent.repository.GradStatusEventRepository;
import ca.bc.gov.educ.api.gradstudent.util.EducGradStudentApiConstants;
import lombok.extern.slf4j.Slf4j;
import net.javacrumbs.shedlock.core.LockAssert;
import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

import static ca.bc.gov.educ.api.gradstudent.constant.EventStatus.DB_COMMITTED;

/**
Expand All @@ -23,35 +23,45 @@ public class JetStreamEventScheduler {
private final GradStatusEventRepository gradStatusEventRepository;
private final Publisher publisher;

private final EducGradStudentApiConstants constants;

/**
* Instantiates a new Stan event scheduler.
*
* @param gradStatusEventRepository the grad status event repository
* @param publisher the publisher
*/
public JetStreamEventScheduler(GradStatusEventRepository gradStatusEventRepository, Publisher publisher) {
public JetStreamEventScheduler(final GradStatusEventRepository gradStatusEventRepository,
final Publisher publisher,
final EducGradStudentApiConstants constants) {
this.gradStatusEventRepository = gradStatusEventRepository;
this.publisher = publisher;
this.constants = constants;
}

/**
* Find and publish grad status events to stan.
*/
@Scheduled(cron = "${cron.scheduled.process.events.stan.run}") // minimum = every 5 minutes
@Scheduled(cron = "${cron.scheduled.process.events.stan.run}")
@SchedulerLock(name = "PUBLISH_GRAD_STATUS_EVENTS_TO_JET_STREAM", lockAtLeastFor = "${cron.scheduled.process.events.stan.lockAtLeastFor}", lockAtMostFor = "${cron.scheduled.process.events.stan.lockAtMostFor}")
public void findAndPublishGradStatusEventsToJetStream() {
log.debug("PUBLISH_GRAD_STATUS_EVENTS_TO_JET_STREAM: started - cron {}, lockAtMostFor {}", constants.getGradToTraxCronRun(), constants.getGradToTraxLockAtMostFor());
LockAssert.assertLocked();
var results = gradStatusEventRepository.findByEventStatusOrderByCreateDate(DB_COMMITTED.toString());
if (!results.isEmpty()) {
results.stream()
.filter(el -> el.getUpdateDate().isBefore(LocalDateTime.now().minusMinutes(5)))
.forEach(el -> {
try {
publisher.dispatchChoreographyEvent(el);
} catch (final Exception ex) {
log.error("Exception while trying to publish message", ex);
}
});
int cnt = 0;
for (GradStatusEvent el : results) {
if (cnt++ >= constants.getGradToTraxProcessingThreshold()) {
log.info(" ==> Reached the processing threshold of {}", constants.getGradToTraxProcessingThreshold());
break;
}
try {
publisher.dispatchChoreographyEvent(el);
} catch (final Exception ex) {
log.error("Exception while trying to publish message", ex);
}
}
log.debug("PUBLISH_GRAD_STATUS_EVENTS_TO_JET_STREAM: processing is completed");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import ca.bc.gov.educ.api.gradstudent.util.EducGradStudentApiConstants;
import ca.bc.gov.educ.api.gradstudent.util.GradValidation;
import ca.bc.gov.educ.api.gradstudent.util.ThreadLocalStateUtil;
import jakarta.transaction.Transactional;
import jakarta.validation.Valid;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -24,9 +26,10 @@
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;

import jakarta.transaction.Transactional;
import jakarta.validation.Valid;
import java.util.*;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

@Service
public class CommonService {
Expand Down Expand Up @@ -202,11 +205,11 @@ public GradStudentAlgorithmData getGradStudentAlgorithmData(String studentID,Str
GradStudentAlgorithmData data = new GradStudentAlgorithmData();
GradSearchStudent gradStudent = gradStudentService.getStudentByStudentIDFromStudentAPI(studentID, accessToken);
GraduationStudentRecord gradStudentRecord = graduationStatusService.getGraduationStatusForAlgorithm(UUID.fromString(studentID));
List<StudentCareerProgram> cpList = new ArrayList<>();
try {
cpList = getAllGradStudentCareerProgramList(studentID, accessToken);
}catch (Exception e) {
logger.debug("TRAX-API-DOWN {}",e.getLocalizedMessage());
List<StudentCareerProgram> cpList = getAllGradStudentCareerProgramList(studentID, accessToken);
GradTraxStudent gradTraxStudent = gradStudentService.getTraxStudentMasterDataByPen(gradStudent.getPen(), accessToken);
if(gradTraxStudent != null) {
gradStudent.setStudentCitizenship(gradTraxStudent.getStudentCitizenship());
gradStudentRecord.setStudentCitizenship(gradTraxStudent.getStudentCitizenship());
}
data.setGradStudent(gradStudent);
data.setGraduationStudentRecord(gradStudentRecord);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import ca.bc.gov.educ.api.gradstudent.util.ThreadLocalStateUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.github.resilience4j.retry.annotation.Retry;
import jakarta.transaction.Transactional;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -20,7 +21,6 @@
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;

import jakarta.transaction.Transactional;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
Expand Down Expand Up @@ -356,6 +356,24 @@ public GradSearchStudent getStudentByStudentIDFromStudentAPI(String studentID, S
return gradStu;
}

@Transactional
@Retry(name = "rt-getTraxStudent")
public GradTraxStudent getTraxStudentMasterDataByPen(String pen, String accessToken) {
final ParameterizedTypeReference<List<GradTraxStudent>> responseType = new ParameterizedTypeReference<>() {
};
List<GradTraxStudent> result = this.webClient.get()
.uri(String.format(constants.getTraxStudentMasterDataByPenUrl(), pen))
.headers(h -> {
h.setBearerAuth(accessToken);
h.set(EducGradStudentApiConstants.CORRELATION_ID, ThreadLocalStateUtil.getCorrelationID());
})
.retrieve().bodyToMono(responseType).block();
if(result != null && !result.isEmpty()) {
return result.get(0);
}
return null;
}

@Transactional
@Retry(name = "searchbyid")
public GraduationStudentRecordDistribution getStudentByStudentIDFromGrad(String studentID) {
Expand All @@ -380,6 +398,18 @@ public List<UUID> getStudentIDsByStatusCode(List<UUID> studentIDs, String status
if (StringUtils.isBlank(statusCode) || studentIDs.isEmpty()) {
return new ArrayList<>();
}
return graduationStatusRepository.filterGivenStudentsByStatusCode(studentIDs, statusCode);
List<UUID> results = new ArrayList<>();
int pageSize = 1000;
int pageNum = studentIDs.size() / pageSize + 1;
for (int i = 0; i < pageNum; i++) {
int startIndex = i * pageSize;
int endIndex = Math.min(startIndex + pageSize, studentIDs.size());
List<UUID> inputIDs = studentIDs.subList(startIndex, endIndex);
List<UUID> responseIDs = graduationStatusRepository.filterGivenStudentsByStatusCode(inputIDs, statusCode);
if (responseIDs != null && !responseIDs.isEmpty()) {
results.addAll(responseIDs);
}
}
return results;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ public class EducGradStudentApiConstants {
public static final String CONV_STUDENT_OPTIONAL_PROGRAM_BY_STUDENT_ID = "/conv/studentoptionalprogram/{optionalProgramID}/{studentID}";
public static final String CONV_STUDENT_CAREER_PROGRAM_BY_STUDENT_ID = "/conv/studentcareerprogram/{careerProgramCode}/{studentID}";

public static final String EDW_GRADUATION_STATUS_SNAPSHOT = "/edw/snapshot";

//Default Date format constants
public static final String DEFAULT_CREATED_BY = "API_GRAD_STUDENT";
public static final String DEFAULT_UPDATED_BY = "API_GRAD_STUDENT";
Expand Down Expand Up @@ -132,6 +134,9 @@ public class EducGradStudentApiConstants {
@Value("${endpoint.grad-trax-api.district-by-district-code.url}")
private String districtByDistrictCodeUrl;

@Value("${endpoint.grad-trax-api.get-student-master-data.url}")
private String traxStudentMasterDataByPenUrl;

@Value("${endpoint.grad-program-api.career_program-by-career-code.url}")
private String careerProgramByCodeUrl;

Expand Down Expand Up @@ -189,4 +194,17 @@ public class EducGradStudentApiConstants {
// Data Conversion option
@Value("${data-conversion.student-guid-pen-xref.enabled}")
private boolean studentGuidPenXrefEnabled;

// Scheduler: ongoing updates from GRAD to TRAX
@Value("${cron.scheduled.process.events.stan.run}")
private String gradToTraxCronRun;

@Value("${cron.scheduled.process.events.stan.lockAtLeastFor}")
private String gradToTraxLockAtLeastFor;

@Value("${cron.scheduled.process.events.stan.lockAtMostFor}")
private String gradToTraxLockAtMostFor;

@Value("${cron.scheduled.process.events.stan.threshold}")
private int gradToTraxProcessingThreshold;
}
3 changes: 3 additions & 0 deletions api/src/main/resources/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ cron:
run: ${CRON_SCHEDULED_PROCESS_EVENTS_STAN}
lockAtLeastFor: ${CRON_SCHEDULED_PROCESS_EVENTS_STAN_LOCK_AT_LEAST_FOR}
lockAtMostFor: ${CRON_SCHEDULED_PROCESS_EVENTS_STAN_LOCK_AT_MOST_FOR}
threshold: ${CRON_SCHEDULED_PROCESS_EVENTS_STAN_THRESHOLD}

#Resilience
resilience4j.retry:
Expand Down Expand Up @@ -150,6 +151,8 @@ resilience4j.retry:
#Endpoint properties
endpoint:
grad-trax-api:
get-student-master-data:
url: ${GRAD_TRAX_API}api/v1/trax/common/student-master/%s
school-by-min-code:
url: ${GRAD_TRAX_API}api/v1/trax/school/%s
district-by-district-code:
Expand Down
Loading

0 comments on commit c57e3bb

Please sign in to comment.