code cleanup and docu

This commit is contained in:
anhefti 2021-05-11 21:55:51 +02:00
parent 70fcbead41
commit 100c5820a2
5 changed files with 38 additions and 41 deletions

View file

@ -32,6 +32,9 @@ import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.NoSEBRestrictionException;
/** The open edX SEB course restriction API implementation.
*
* See also : https://seb-openedx.readthedocs.io/en/latest/ */
public class OpenEdxCourseRestriction {
private static final Logger log = LoggerFactory.getLogger(OpenEdxCourseRestriction.class);
@ -43,7 +46,6 @@ public class OpenEdxCourseRestriction {
private final LmsSetup lmsSetup;
private final JSONMapper jsonMapper;
private final OpenEdxRestTemplateFactory openEdxRestTemplateFactory;
private final int restrictionAPIPushCount;
private OAuth2RestTemplate restTemplate;
@ -56,7 +58,6 @@ public class OpenEdxCourseRestriction {
this.lmsSetup = lmsSetup;
this.jsonMapper = jsonMapper;
this.openEdxRestTemplateFactory = openEdxRestTemplateFactory;
this.restrictionAPIPushCount = restrictionAPIPushCount;
}
LmsSetupTestResult initAPIAccess() {
@ -145,9 +146,9 @@ public class OpenEdxCourseRestriction {
log.debug("PUT SEB Client restriction on course: {} : {}", courseId, restriction);
}
return handleSEBRestriction(processSEBRestrictionUpdate(pushSEBRestrictionFunction(
return handleSEBRestriction(pushSEBRestrictionFunction(
restriction,
courseId)));
courseId));
}
Result<Boolean> deleteSEBRestriction(final String courseId) {
@ -156,41 +157,7 @@ public class OpenEdxCourseRestriction {
log.debug("DELETE SEB Client restriction on course: {}", courseId);
}
return handleSEBRestriction(processSEBRestrictionUpdate(deleteSEBRestrictionFunction(courseId)));
}
private BooleanSupplier processSEBRestrictionUpdate(final BooleanSupplier restrictionUpdate) {
return () -> {
if (this.restrictionAPIPushCount > 0) {
// NOTE: This is a temporary work-around for SEB Restriction API within Open edX SEB integration plugin to
// apply on load-balanced infrastructure or infrastructure that has several layers of cache.
// The reason for this is that the API (Open edX system) internally don't apply a resource-change that is
// done within HTTP API call immediately from an outside perspective.
// After a resource-change on the API is done, the system toggles between the old and the new resource
// while constantly calling GET. This usually happens for about a minute or two then it stabilizes on the new resource
//
// This may source on load-balancing or internally caching on Open edX side.
// To mitigate this effect the SEB Server can be configured to apply a resource-change on the
// API several times in a row to flush as match caches and reach as match as possible server instances.
//
// Since this is a brute-force method to mitigate the problem, this should only be a temporary
// work-around until a better solution on Open edX SEB integration side has been found and applied.
log.warn("SEB restriction update with multiple API push "
+ "(this is a temporary work-around for SEB Restriction API within Open edX SEB integration plugin)");
for (int i = 0; i < this.restrictionAPIPushCount; i++) {
if (!restrictionUpdate.getAsBoolean()) {
Result.ofRuntimeError(
"Failed to process SEB restriction update. See logs for more information");
}
}
return true;
} else {
return restrictionUpdate.getAsBoolean();
}
};
return handleSEBRestriction(deleteSEBRestrictionFunction(courseId));
}
private BooleanSupplier pushSEBRestrictionFunction(

View file

@ -31,6 +31,10 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate;
/** The OpenEdxLmsAPITemplate is separated into two parts:
* - OpenEdxCourseAccess implements the course access API
* - OpenEdxCourseRestriction implements the SEB restriction API
* - Both uses the OpenEdxRestTemplateFactory to create a spring based RestTemplate to access the LMS API */
final class OpenEdxLmsAPITemplate implements LmsAPITemplate {
private static final Logger log = LoggerFactory.getLogger(OpenEdxLmsAPITemplate.class);

View file

@ -51,7 +51,17 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.MoodleRestT
/** Implements the LmsAPITemplate for Open edX LMS Course API access.
*
* See also: https://docs.moodle.org/dev/Web_service_API_functions */
* See also: https://docs.moodle.org/dev/Web_service_API_functions
*
* NOTE: Because of the missing integration on Moodle side so far the MoodleCourseAccess
* needs to deal with Moodle's standard API functions that don't allow to filter and page course/quiz data
* in an easy and proper way. Therefore we have to fetch all course and quiz data from Moodle before
* filtering and paging can be applied. Since there are possibly thousands of active courses and quizzes
* this moodle course access implements an synchronous fetch as well as an asynchronous fetch strategy.
* The asynchronous fetch strategy is started within a background task and fill up a shared cache.
* A request will start the background task if needed and return immediately to do not block the request.
* The planed Moodle integration on moodle side also defines an improved course access API. This will
* possibly make this synchronous fetch strategy obsolete in the future. */
public class MoodleCourseAccess extends CourseAccess {
private static final long INITIAL_WAIT_TIME = 3 * Constants.SECOND_IN_MILLIS;
@ -253,6 +263,7 @@ public class MoodleCourseAccess extends CourseAccess {
final DateTime quizFromTime = (filterMap != null) ? filterMap.getQuizFromTime() : null;
final long fromCutTime = (quizFromTime != null) ? Utils.toUnixTimeInSeconds(quizFromTime) : -1;
// Verify and call the proper strategy to get the course and quiz data
Collection<CourseDataShort> courseQuizData = Collections.emptyList();
if (this.moodleCourseDataAsyncLoader.isRunning()) {
courseQuizData = this.moodleCourseDataAsyncLoader.getCachedCourseData();

View file

@ -53,6 +53,8 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.MoodleRestT
@Component
@WebServiceProfile
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
/** This implements the (temporary) asynchronous fetch strategy to fetch
* course and quiz data within a background task and fill up a shared cache. */
public class MoodleCourseDataAsyncLoader {
private static final Logger log = LoggerFactory.getLogger(MoodleCourseDataAsyncLoader.class);

View file

@ -32,6 +32,20 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.NoSEBRestrictionException;
/** The MoodleLmsAPITemplate is separated into two parts:
* - MoodleCourseAccess implements the course access API
* - MoodleCourseRestriction implements the SEB restriction API
* - Both uses the MoodleRestTemplateFactore to create a spring based RestTemplate to access the LMS API
*
* NOTE: Because of the missing integration on Moodle side so far the MoodleCourseAccess
* needs to deal with Moodle's standard API functions that don't allow to filter and page course/quiz data
* in an easy and proper way. Therefore we have to fetch all course and quiz data from Moodle before
* filtering and paging can be applied. Since there are possibly thousands of active courses and quizzes
* this moodle course access implements an synchronous fetch as well as an asynchronous fetch strategy.
* The asynchronous fetch strategy is started within a background task and fill up a shared cache.
* A request will start the background task if needed and return immediately to do not block the request.
* The planed Moodle integration on moodle side also defines an improved course access API. This will
* possibly make this synchronous fetch strategy obsolete in the future. */
public class MoodleLmsAPITemplate implements LmsAPITemplate {
private static final Logger log = LoggerFactory.getLogger(MoodleLmsAPITemplate.class);
@ -63,7 +77,6 @@ public class MoodleLmsAPITemplate implements LmsAPITemplate {
@Override
public LmsSetupTestResult testCourseRestrictionAPI() {
throw new NoSEBRestrictionException();
//return this.moodleCourseRestriction.initAPIAccess();
}
@Override