Skip to content

Commit

Permalink
SEBSP-116 try to recover when exam and groups do not exist anymore on…
Browse files Browse the repository at this point in the history
… SPS
  • Loading branch information
anhefti committed Dec 12, 2024
1 parent 1ef877d commit ee471e5
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,6 @@ public interface ScreenProctoringGroupDAO {
* @return Result refer to the group or to an error when happened */
Result<ScreenProctoringGroup> getScreenProctoringGroup(String uuid);

/** Get the group record with specified name for a given exam.
*
* @param examId the exam identifier
* @param groupName the name of the group
* @return Result refer to the group record or to an error when happened */
Result<ScreenProctoringGroup> getGroupByName(Long examId, String groupName);

/** Get all collecting group that exists for a given exam.
*
* @param examId the exam identifier
Expand Down Expand Up @@ -85,4 +78,6 @@ public interface ScreenProctoringGroupDAO {
boolean hasActiveGroups();

void updateName(Long id, String name);

Result<ScreenProctoringGroup> updateFromSPS(Long id, ScreenProctoringGroup groupOnSPS);
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,20 +97,6 @@ public Result<ScreenProctoringGroup> getScreenProctoringGroup(final String uuid)
.map(this::toDomainModel);
}

@Override
@Transactional(readOnly = true)
public Result<ScreenProctoringGroup> getGroupByName(final Long examId, final String groupName) {
return Result.tryCatch(() -> {
return this.screenProctoringGroopRecordMapper.selectByExample()
.where(ScreenProctoringGroopRecordDynamicSqlSupport.examId, isEqualTo(examId))
.and(ScreenProctoringGroopRecordDynamicSqlSupport.name, isEqualTo(groupName))
.build()
.execute()
.get(0);
})
.map(this::toDomainModel);
}

@Override
@Transactional(readOnly = true)
public Result<Collection<ScreenProctoringGroup>> getCollectingGroups(final Long examId) {
Expand Down Expand Up @@ -318,6 +304,26 @@ public void updateName(final Long groupId, final String name) {
}
}

@Override
@Transactional
public Result<ScreenProctoringGroup> updateFromSPS(final Long id, final ScreenProctoringGroup groupOnSPS) {
return Result.tryCatch(() -> {
UpdateDSL
.updateWithMapper(
this.screenProctoringGroopRecordMapper::update,
ScreenProctoringGroopRecordDynamicSqlSupport.screenProctoringGroopRecord)
.set(ScreenProctoringGroopRecordDynamicSqlSupport.uuid).equalTo(groupOnSPS.uuid)
.set(ScreenProctoringGroopRecordDynamicSqlSupport.data).equalTo(groupOnSPS.additionalData)
.where(ScreenProctoringGroopRecordDynamicSqlSupport.id, isEqualTo(id))
.build()
.execute();

return id;
})
.flatMap(this::getScreenProctoringGroup)
.onError(TransactionHandler::rollback);
}

private ScreenProctoringGroup toDomainModel(final ScreenProctoringGroopRecord record) {
return new ScreenProctoringGroup(
record.getId(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ ResponseEntity<String> testServiceConnection() {
if (errors.contains("Connection refused")) {
return new ResponseEntity<>( errors, HttpStatus.SERVICE_UNAVAILABLE);
}
// TODO Test SSL error

return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,13 @@ Result<Exam> startScreenProctoring(final Exam exam) {
log.info("SPS Exam for SEB Server Exam: {} already exists. Try to re-activate", exam.externalId);

final SPSData spsData = this.getSPSData(exam.id);

if (!existsExamOnSPS(exam)) {
log.warn("Exam does not exist on SPS but has local data. Try to reinitialize Screen Proctoring for exam: {}", exam.name);
initializeScreenProctoring(exam, apiTemplate);
return exam;
}

// re-activate all needed entities on SPS side
if (exam.status == Exam.ExamStatus.RUNNING) {
activateScreenProctoring(exam).getOrThrow();
Expand Down Expand Up @@ -416,8 +423,26 @@ private void synchronizeFromSEBGroups(
} else {
log.warn(
"Screen Proctoring group mismatch detected. No SPS group found for exam: {} and local group: {}",
exam,
exam.name,
existing);
log.info("Try to create new one on SPS");
try {
final ScreenProctoringGroup groupOnSPS = createGroupOnSPS(
0,
exam.id,
sebGroup.name,
spsData.spsExamUUID,
existing.isFallback,
sebGroup.id,
apiTemplate);

this.screenProctoringGroupDAO
.updateFromSPS(existing.id, groupOnSPS)
.getOrThrow();

} catch (final Exception e) {
log.error("Failed to synchronize SEB Group on SPS: {}", sebGroup, e);
}
}
}
}
Expand Down Expand Up @@ -476,11 +501,30 @@ private void synchronizeDefaultGroup(
final SPSGroup spsGroup = spsGroups.get(localGroup.uuid);

if (spsGroup == null) {
// try re-create group on SPS
log.warn(
"Expecting only one default SPS group for exam: {} but there are local groups: {} and groups on SPS: {}",
exam,
localGroups.values(),
spsGroups.values());
"Screen Proctoring group mismatch detected. No SPS group found for exam: {} and local group: {}",
exam.name,
localGroup);
log.info("Try to create new one on SPS");
try {
final ScreenProctoringGroup groupOnSPS = createGroupOnSPS(
0,
exam.id,
localGroup.name,
spsData.spsExamUUID,
localGroup.isFallback,
localGroup.id,
apiTemplate);

this.screenProctoringGroupDAO
.updateFromSPS(localGroup.id, groupOnSPS)
.getOrThrow();

} catch (final Exception e) {
log.error("Failed to synchronize SEB Group on SPS: {}", localGroup, e);
}
return;
}

// if name has changed synchronize locally
Expand Down Expand Up @@ -597,9 +641,9 @@ private Collection<SPSGroup> getSPSGroups(
/** This is called when an exam has changed its parameter and needs data update on SPS side
*
* @param exam The exam*/
void updateExam(final Exam exam) {

try {
Result<Exam> updateExam(final Exam exam) {
return Result.tryCatch(() -> {
final SPSData spsData = this.getSPSData(exam.id);
final ScreenProctoringServiceOAuthTemplate apiTemplate = this.getAPITemplate(exam.id);
final ScreenProctoringSettings settings = this.proctoringSettingsDAO
Expand All @@ -621,9 +665,9 @@ void updateExam(final Exam exam) {
exam.getType().name(),
exam.startTime != null ? exam.startTime.getMillis() : null,
exam.endTime != null ? exam.endTime.getMillis() : null,
settings.deletionTime != null ? settings.deletionTime.getMillis() : null,
settings.deletionTime != null ? settings.deletionTime.getMillis() : null,
supporterIds
);
);

final String jsonExamUpdate = this.jsonMapper.writeValueAsString(examUpdate);

Expand All @@ -632,13 +676,13 @@ void updateExam(final Exam exam) {
HttpMethod.PUT,
jsonExamUpdate,
apiTemplate.getHeadersJSONRequest());

if (exchange.getStatusCode() != HttpStatus.OK) {
log.error("Failed to update SPS exam data: {}", exchange);
throw new RuntimeException("Failed to update SPS exam data: " + exchange);
}

} catch (final Exception e) {
log.error("Failed to update exam on SPS service for exam: {}", exam, e);
}

return exam;
});
}

/** This is called when an exam finishes and deactivates the Exam, SEB Client Access on Screen Proctoring Service side.
Expand Down Expand Up @@ -704,7 +748,7 @@ Result<Exam> activateScreenProctoring(final Exam exam) {
private void initializeScreenProctoring(
final Exam exam,
final ScreenProctoringServiceOAuthTemplate apiTemplate) throws JsonProcessingException {

final SPSData spsData = new SPSData();
log.info(
"SPS Exam for SEB Server Exam: {} don't exists yet, create necessary structures on SPS",
Expand Down Expand Up @@ -826,7 +870,7 @@ Tuple<String> createSEBSession(

final String key = exchange1.getHeaders().getFirst(SESSION_ENCRYPTION_KEY_REQUEST_HEADER);
if (StringUtils.isBlank(key)) {
log.error("Failed to get SEB session encryption key form SPS");
log.error("Failed to get SEB session encryption key from SPS");
}

return new Tuple<>(token, key);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ public Result<Exam> applyScreenProctoringForExam(final EntityKey entityKey) {

this.examDAO.markUpdate(exam.id);
} else if (isEnabling) {
this.screenProctoringAPIBinding.updateExam(exam);
this.screenProctoringAPIBinding.updateExam(exam).getOrThrow();
this.screenProctoringAPIBinding.synchronizeGroups(exam);
}

Expand Down Expand Up @@ -343,7 +343,9 @@ public void notifyExamSaved(final Exam exam) {
}

this.screenProctoringAPIBinding.synchronizeUserAccounts(exam);
this.screenProctoringAPIBinding.updateExam(exam);
this.screenProctoringAPIBinding
.updateExam(exam)
.onError(error -> log.warn("Failed to update exam on SPS: ", error));
this.screenProctoringAPIBinding.synchronizeGroups(exam);
}

Expand Down Expand Up @@ -488,8 +490,6 @@ private void closeScreenProctoringSession(final ClientConnectionRecord ccRecord)
}
}



private void applyScreenProctoringSession(final ClientConnectionRecord ccRecord) {
try {

Expand Down

0 comments on commit ee471e5

Please sign in to comment.