code cleanup and docu
This commit is contained in:
parent
70fcbead41
commit
100c5820a2
5 changed files with 38 additions and 41 deletions
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue