Filter fromDate in Moodle lookup

This commit is contained in:
anhefti 2020-12-17 18:03:56 +01:00
parent 3cefcbe3f3
commit 7fcfcf1445
4 changed files with 44 additions and 10 deletions

View file

@ -43,7 +43,7 @@ public abstract class CourseAccess {
protected CourseAccess(final AsyncService asyncService) {
this.allQuizzesRequest = asyncService.createMemoizingCircuitBreaker(
allQuizzesSupplier(),
allQuizzesSupplier(null),
3,
Constants.MINUTE_IN_MILLIS,
Constants.MINUTE_IN_MILLIS,
@ -101,6 +101,9 @@ public abstract class CourseAccess {
}
public Result<List<QuizData>> getQuizzes(final FilterMap filterMap) {
if (filterMap != null) {
this.allQuizzesRequest.setSupplier(allQuizzesSupplier(filterMap));
}
return this.allQuizzesRequest.get()
.map(LmsAPIService.quizzesFilterFunction(filterMap));
}
@ -136,7 +139,7 @@ public abstract class CourseAccess {
protected abstract Supplier<List<QuizData>> quizzesSupplier(final Set<String> ids);
protected abstract Supplier<List<QuizData>> allQuizzesSupplier();
protected abstract Supplier<List<QuizData>> allQuizzesSupplier(final FilterMap filterMap);
protected abstract Supplier<Chapters> getCourseChaptersSupplier(final String courseId);

View file

@ -49,6 +49,7 @@ import ch.ethz.seb.sebserver.gbl.model.user.ExamineeAccountDetails;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.webservice.WebserviceInfo;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.CourseAccess;
/** Implements the LmsAPITemplate for Open edX LMS Course API access.
@ -173,7 +174,7 @@ final class OpenEdxCourseAccess extends CourseAccess {
}
@Override
protected Supplier<List<QuizData>> allQuizzesSupplier() {
protected Supplier<List<QuizData>> allQuizzesSupplier(final FilterMap filterMap) {
return () -> getRestTemplate()
.map(this::collectAllQuizzes)
.getOrThrow();

View file

@ -20,6 +20,7 @@ import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.LinkedMultiValueMap;
@ -40,6 +41,7 @@ import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult;
import ch.ethz.seb.sebserver.gbl.model.user.ExamineeAccountDetails;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.CourseAccess;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.MoodleRestTemplateFactory.MoodleAPIRestTemplate;
@ -48,6 +50,8 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.MoodleRestT
* See also: https://docs.moodle.org/dev/Web_service_API_functions */
public class MoodleCourseAccess extends CourseAccess {
private static final long INITIAL_WAIT_TIME = 3 * Constants.SECOND_IN_MILLIS;
private static final Logger log = LoggerFactory.getLogger(MoodleCourseAccess.class);
private static final String MOODLE_QUIZ_START_URL_PATH = "mod/quiz/view.php?id=";
@ -172,9 +176,9 @@ public class MoodleCourseAccess extends CourseAccess {
}
@Override
protected Supplier<List<QuizData>> allQuizzesSupplier() {
protected Supplier<List<QuizData>> allQuizzesSupplier(final FilterMap filterMap) {
return () -> getRestTemplate()
.map(template -> collectAllQuizzes(template))
.map(template -> collectAllQuizzes(template, filterMap))
.getOrThrow();
}
@ -183,34 +187,51 @@ public class MoodleCourseAccess extends CourseAccess {
throw new UnsupportedOperationException("not available yet");
}
private List<QuizData> collectAllQuizzes(final MoodleAPIRestTemplate restTemplate) {
private List<QuizData> collectAllQuizzes(
final MoodleAPIRestTemplate restTemplate,
final FilterMap filterMap) {
final String urlPrefix = (this.lmsSetup.lmsApiUrl.endsWith(Constants.URL_PATH_SEPARATOR))
? this.lmsSetup.lmsApiUrl + MOODLE_QUIZ_START_URL_PATH
: this.lmsSetup.lmsApiUrl + Constants.URL_PATH_SEPARATOR + MOODLE_QUIZ_START_URL_PATH;
final DateTime quizFromTime = (filterMap != null) ? filterMap.getQuizFromTime() : null;
final long fromCutTime = (quizFromTime != null) ? Utils.toUnixTimeInSeconds(quizFromTime) : -1;
Collection<CourseData> courseQuizData = Collections.emptyList();
if (this.moodleCourseDataLazyLoader.isRunning()) {
courseQuizData = this.moodleCourseDataLazyLoader.getPreFilteredCourseIds();
} else if (this.moodleCourseDataLazyLoader.getLastRunTime() <= 0) {
// set cut time if available
if (fromCutTime >= 0) {
this.moodleCourseDataLazyLoader.setFromCutTime(fromCutTime);
}
// first run async and wait some time, get what is there
this.moodleCourseDataLazyLoader.loadAsync(restTemplate);
try {
Thread.sleep(5 * Constants.SECOND_IN_MILLIS);
Thread.sleep(INITIAL_WAIT_TIME);
courseQuizData = this.moodleCourseDataLazyLoader.getPreFilteredCourseIds();
} catch (final Exception e) {
log.error("Failed to wait for first load run: ", e);
return Collections.emptyList();
}
} else if (this.moodleCourseDataLazyLoader.isLongRunningTask()) {
// kick off the task again when old asynchronously and take back what is there instantly
if (Utils.getMillisecondsNow() - this.moodleCourseDataLazyLoader.getLastRunTime() > 10
// on long running tasks if we have a different fromCutTime as before
// kick off the lazy loadung task imeditially with the new time filter
if (fromCutTime > 0 && fromCutTime != this.moodleCourseDataLazyLoader.getFromCutTime()) {
this.moodleCourseDataLazyLoader.setFromCutTime(fromCutTime);
this.moodleCourseDataLazyLoader.loadAsync(restTemplate);
// otherwise kick off only if the last fetch task was then minutes ago
} else if (Utils.getMillisecondsNow() - this.moodleCourseDataLazyLoader.getLastRunTime() > 10
* Constants.MINUTE_IN_MILLIS) {
this.moodleCourseDataLazyLoader.loadAsync(restTemplate);
}
courseQuizData = this.moodleCourseDataLazyLoader.getPreFilteredCourseIds();
} else {
// just run the task in sync
if (fromCutTime >= 0) {
this.moodleCourseDataLazyLoader.setFromCutTime(fromCutTime);
}
this.moodleCourseDataLazyLoader.loadSync(restTemplate);
courseQuizData = this.moodleCourseDataLazyLoader.getPreFilteredCourseIds();
}

View file

@ -65,7 +65,7 @@ public class MoodleCourseDataLazyLoader {
private long lastLoadTime = 0;
private boolean running = false;
private final long fromCutTime = DateTime.now(DateTimeZone.UTC).minusYears(3).getMillis() / 1000;
private long fromCutTime;
public MoodleCourseDataLazyLoader(
final JSONMapper jsonMapper,
@ -73,6 +73,15 @@ public class MoodleCourseDataLazyLoader {
this.jsonMapper = jsonMapper;
this.asyncRunner = asyncRunner;
this.fromCutTime = Utils.toUnixTimeInSeconds(DateTime.now(DateTimeZone.UTC).minusYears(3));
}
public long getFromCutTime() {
return this.fromCutTime;
}
public void setFromCutTime(final long fromCutTime) {
this.fromCutTime = fromCutTime;
}
public Set<CourseData> getPreFilteredCourseIds() {