better seb restriction update handling
This commit is contained in:
parent
810b6dc8c2
commit
2d016ed7fc
6 changed files with 96 additions and 42 deletions
|
@ -87,6 +87,13 @@ public interface LmsAPITemplate {
|
||||||
* @return Result refer to the given SebRestrictionData if restriction was successful or to an error if not */
|
* @return Result refer to the given SebRestrictionData if restriction was successful or to an error if not */
|
||||||
Result<SebRestrictionData> applySebClientRestriction(SebRestrictionData sebRestrictionData);
|
Result<SebRestrictionData> applySebClientRestriction(SebRestrictionData sebRestrictionData);
|
||||||
|
|
||||||
|
/** Updates a SEB Client restriction within the LMS with the given attributes.
|
||||||
|
*
|
||||||
|
* @param sebRestrictionData containing all data for SEB Client restriction
|
||||||
|
* @return Result refer to the given SebRestrictionData if updating restriction was successful or to an error if
|
||||||
|
* not */
|
||||||
|
Result<SebRestrictionData> updateSebClientRestriction(SebRestrictionData sebRestrictionData);
|
||||||
|
|
||||||
/** Releases an already applied SEB Client restriction within the LMS for a given Exam.
|
/** Releases an already applied SEB Client restriction within the LMS for a given Exam.
|
||||||
* This completely removes the SEB Client restriction on LMS side.
|
* This completely removes the SEB Client restriction on LMS side.
|
||||||
*
|
*
|
||||||
|
|
|
@ -149,6 +149,12 @@ final class MockupLmsAPITemplate implements LmsAPITemplate {
|
||||||
return Result.of(sebRestrictionData);
|
return Result.of(sebRestrictionData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Result<SebRestrictionData> updateSebClientRestriction(final SebRestrictionData sebRestrictionData) {
|
||||||
|
log.info("Update SEB Client restriction: {}", sebRestrictionData);
|
||||||
|
return Result.of(sebRestrictionData);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Result<Exam> releaseSebClientRestriction(final Exam exam) {
|
public Result<Exam> releaseSebClientRestriction(final Exam exam) {
|
||||||
log.info("Release SEB Client restriction for Exam: {}", exam);
|
log.info("Release SEB Client restriction for Exam: {}", exam);
|
||||||
|
|
|
@ -191,6 +191,20 @@ final class OpenEdxLmsAPITemplate implements LmsAPITemplate {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Result<SebRestrictionData> updateSebClientRestriction(final SebRestrictionData sebRestrictionData) {
|
||||||
|
return Result.tryCatch(() -> {
|
||||||
|
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("Update SEB Client restriction: {}", sebRestrictionData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
return sebRestrictionData;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Result<Exam> releaseSebClientRestriction(final Exam exam) {
|
public Result<Exam> releaseSebClientRestriction(final Exam exam) {
|
||||||
return Result.tryCatch(() -> {
|
return Result.tryCatch(() -> {
|
||||||
|
|
|
@ -18,7 +18,6 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
|
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
|
||||||
|
@ -74,7 +73,6 @@ public class ExamConfigUpdateServiceImpl implements ExamConfigUpdateService {
|
||||||
// generate the new Config Key and update the Config Key within the LMSSetup API for each exam (delete old Key and add new Key)
|
// generate the new Config Key and update the Config Key within the LMSSetup API for each exam (delete old Key and add new Key)
|
||||||
// evict each Exam from cache and release the update-lock on DB
|
// evict each Exam from cache and release the update-lock on DB
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
|
||||||
public Result<Collection<Long>> processExamConfigurationChange(final Long configurationNodeId) {
|
public Result<Collection<Long>> processExamConfigurationChange(final Long configurationNodeId) {
|
||||||
|
|
||||||
final String updateId = this.examUpdateHandler.createUpdateId();
|
final String updateId = this.examUpdateHandler.createUpdateId();
|
||||||
|
@ -172,7 +170,6 @@ public class ExamConfigUpdateServiceImpl implements ExamConfigUpdateService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
|
||||||
public <T> Result<T> processExamConfigurationMappingChange(
|
public <T> Result<T> processExamConfigurationMappingChange(
|
||||||
final ExamConfigurationMap mapping,
|
final ExamConfigurationMap mapping,
|
||||||
final Function<ExamConfigurationMap, Result<T>> changeAction) {
|
final Function<ExamConfigurationMap, Result<T>> changeAction) {
|
||||||
|
@ -205,29 +202,35 @@ public class ExamConfigUpdateServiceImpl implements ExamConfigUpdateService {
|
||||||
// check again if there are no new active client connections in the meantime
|
// check again if there are no new active client connections in the meantime
|
||||||
checkActiveClientConnections(exam);
|
checkActiveClientConnections(exam);
|
||||||
|
|
||||||
// apply the referenced change action
|
// apply the referenced change action. On error the change is rolled back and
|
||||||
|
// this processing returns immediately with the error
|
||||||
final T result = changeAction.apply(mapping)
|
final T result = changeAction.apply(mapping)
|
||||||
.getOrThrow();
|
.onError(t -> log.error("Fauled to save exam configuration: {}",
|
||||||
|
mapping.configurationNodeId))
|
||||||
// flush the exam cache
|
|
||||||
this.examSessionService.flushCache(exam)
|
|
||||||
.getOrThrow();
|
.getOrThrow();
|
||||||
|
|
||||||
// update seb client restriction if the feature is activated
|
// update seb client restriction if the feature is activated
|
||||||
if (exam.lmsSebRestriction) {
|
if (exam.lmsSebRestriction) {
|
||||||
final Result<Exam> updateSebClientRestriction = this.updateSebClientRestriction(exam);
|
final Result<Exam> updateSebClientRestriction = this.updateSebClientRestriction(exam);
|
||||||
|
// if there was an error during update, it is logged but this process goes on
|
||||||
|
// and the saved changes are not rolled back
|
||||||
if (updateSebClientRestriction.hasError()) {
|
if (updateSebClientRestriction.hasError()) {
|
||||||
log.error("Failed to update SEB Client restriction on LMS for exam: {}", exam);
|
log.error("Failed to update SEB Client restriction on LMS for exam: {}", exam);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// release the lock
|
// flush the exam cache. If there was an error during flush, it is logged but this process goes on
|
||||||
|
// and the saved changes are not rolled back
|
||||||
|
this.examSessionService.flushCache(exam)
|
||||||
|
.onError(t -> log.error("Failed to flush cache for exam: {}", exam));
|
||||||
|
|
||||||
|
// release the exam lock
|
||||||
this.examDAO.releaseLock(exam.id, updateId)
|
this.examDAO.releaseLock(exam.id, updateId)
|
||||||
.getOrThrow();
|
.onError(t -> log.error("Failed to release lock for exam: {}", exam));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
})
|
})
|
||||||
.onError(TransactionHandler::rollback);
|
.onError(t -> this.examDAO.forceUnlock(mapping.examId));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,20 +283,17 @@ public class ExamConfigUpdateServiceImpl implements ExamConfigUpdateService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Result<Exam> applySebClientRestriction(final Exam exam) {
|
public Result<Exam> applySebClientRestriction(final Exam exam) {
|
||||||
return this.examUpdateHandler.applySebClientRestriction(exam)
|
return this.examUpdateHandler.applySebClientRestriction(exam);
|
||||||
.onError(error -> log.error("Failed to apply SEB Client restriction for Exam: {}", exam, error));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Result<Exam> updateSebClientRestriction(final Exam exam) {
|
public Result<Exam> updateSebClientRestriction(final Exam exam) {
|
||||||
return this.examUpdateHandler.updateSebClientRestriction(exam)
|
return this.examUpdateHandler.updateSebClientRestriction(exam);
|
||||||
.onError(error -> log.error("Failed to update SEB Client restriction for Exam: {}", exam, error));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Result<Exam> releaseSebClientRestriction(final Exam exam) {
|
public Result<Exam> releaseSebClientRestriction(final Exam exam) {
|
||||||
return this.examUpdateHandler.releaseSebClientRestriction(exam)
|
return this.examUpdateHandler.releaseSebClientRestriction(exam);
|
||||||
.onError(error -> log.error("Failed to release SEB Client restriction for Exam: {}", exam, error));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkIntegrityDoubleCheck(
|
private void checkIntegrityDoubleCheck(
|
||||||
|
|
|
@ -126,24 +126,7 @@ class ExamUpdateHandler {
|
||||||
|
|
||||||
return Result.tryCatch(() -> {
|
return Result.tryCatch(() -> {
|
||||||
|
|
||||||
final Collection<String> configKeys = this.sebExamConfigService
|
final SebRestrictionData sebRestrictionData = createSebRestrictionData(exam);
|
||||||
.generateConfigKeys(exam.institutionId, exam.id)
|
|
||||||
.getOrThrow();
|
|
||||||
|
|
||||||
final Collection<String> browserExamKeys = new ArrayList<>();
|
|
||||||
final String browserExamKeysString = exam.getBrowserExamKeys();
|
|
||||||
if (StringUtils.isNotBlank(browserExamKeysString)) {
|
|
||||||
browserExamKeys.addAll(Arrays.asList(StringUtils.split(
|
|
||||||
browserExamKeysString,
|
|
||||||
Constants.LIST_SEPARATOR)));
|
|
||||||
}
|
|
||||||
|
|
||||||
final SebRestrictionData sebRestrictionData = new SebRestrictionData(
|
|
||||||
exam,
|
|
||||||
configKeys,
|
|
||||||
browserExamKeys,
|
|
||||||
// TODO when we have more restriction details available form the Exam, put it to the map
|
|
||||||
Collections.emptyMap());
|
|
||||||
|
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debug("Appling SEB Client restriction on LMS with: {}", sebRestrictionData);
|
log.debug("Appling SEB Client restriction on LMS with: {}", sebRestrictionData);
|
||||||
|
@ -166,11 +149,20 @@ class ExamUpdateHandler {
|
||||||
return Result.of(exam);
|
return Result.of(exam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Result.tryCatch(() -> {
|
||||||
|
|
||||||
|
final SebRestrictionData sebRestrictionData = createSebRestrictionData(exam);
|
||||||
|
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debug("Update SEB Client restrictions for exam: {}", exam);
|
log.debug("Update SEB Client restrictions for exam: {}", exam);
|
||||||
}
|
}
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
return this.lmsAPIService
|
||||||
|
.getLmsAPITemplate(exam.lmsSetupId)
|
||||||
|
.flatMap(lmsTemplate -> lmsTemplate.updateSebClientRestriction(sebRestrictionData))
|
||||||
|
.map(data -> exam)
|
||||||
|
.getOrThrow();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Exam> releaseSebClientRestriction(final Exam exam) {
|
Result<Exam> releaseSebClientRestriction(final Exam exam) {
|
||||||
|
@ -184,4 +176,39 @@ class ExamUpdateHandler {
|
||||||
.flatMap(template -> template.releaseSebClientRestriction(exam));
|
.flatMap(template -> template.releaseSebClientRestriction(exam));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Transactional
|
||||||
|
// public <T> Result<T> updateExamConfigurationMappingChange(
|
||||||
|
// final ExamConfigurationMap mapping,
|
||||||
|
// final Function<ExamConfigurationMap, Result<T>> changeAction,
|
||||||
|
// final Exam exam) {
|
||||||
|
//
|
||||||
|
// return Result.tryCatch(() -> {
|
||||||
|
//
|
||||||
|
// return result;
|
||||||
|
// })
|
||||||
|
// .onError(TransactionHandler::rollback);
|
||||||
|
// }
|
||||||
|
|
||||||
|
private SebRestrictionData createSebRestrictionData(final Exam exam) {
|
||||||
|
final Collection<String> configKeys = this.sebExamConfigService
|
||||||
|
.generateConfigKeys(exam.institutionId, exam.id)
|
||||||
|
.getOrThrow();
|
||||||
|
|
||||||
|
final Collection<String> browserExamKeys = new ArrayList<>();
|
||||||
|
final String browserExamKeysString = exam.getBrowserExamKeys();
|
||||||
|
if (StringUtils.isNotBlank(browserExamKeysString)) {
|
||||||
|
browserExamKeys.addAll(Arrays.asList(StringUtils.split(
|
||||||
|
browserExamKeysString,
|
||||||
|
Constants.LIST_SEPARATOR)));
|
||||||
|
}
|
||||||
|
|
||||||
|
final SebRestrictionData sebRestrictionData = new SebRestrictionData(
|
||||||
|
exam,
|
||||||
|
configKeys,
|
||||||
|
browserExamKeys,
|
||||||
|
// TODO when we have more restriction details available form the Exam, put it to the map
|
||||||
|
Collections.emptyMap());
|
||||||
|
return sebRestrictionData;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,7 +194,7 @@ public class ExamConfigurationMappingController extends EntityController<ExamCon
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
ConfigurationStatus.IN_USE))
|
ConfigurationStatus.READY_TO_USE))
|
||||||
.map(id -> pair);
|
.map(id -> pair);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue