LMS Template API
This commit is contained in:
parent
29248898ff
commit
49b2ffe338
8 changed files with 14 additions and 45 deletions
|
@ -46,12 +46,10 @@ import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||||
* @param <T> The of the result of the supplying function */
|
* @param <T> The of the result of the supplying function */
|
||||||
public final class MemoizingCircuitBreaker<T> implements Supplier<Result<T>> {
|
public final class MemoizingCircuitBreaker<T> implements Supplier<Result<T>> {
|
||||||
|
|
||||||
// TODO considering invalidation time for memoizing
|
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(MemoizingCircuitBreaker.class);
|
private static final Logger log = LoggerFactory.getLogger(MemoizingCircuitBreaker.class);
|
||||||
|
|
||||||
private final CircuitBreaker<T> delegate;
|
private final CircuitBreaker<T> delegate;
|
||||||
private final Supplier<T> supplier;
|
private Supplier<T> supplier;
|
||||||
|
|
||||||
private final boolean memoizing;
|
private final boolean memoizing;
|
||||||
private final long maxMemoizingTime;
|
private final long maxMemoizingTime;
|
||||||
|
@ -121,6 +119,10 @@ public final class MemoizingCircuitBreaker<T> implements Supplier<Result<T>> {
|
||||||
this.maxMemoizingTime = maxMemoizingTime;
|
this.maxMemoizingTime = maxMemoizingTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSupplier(final Supplier<T> supplier) {
|
||||||
|
this.supplier = supplier;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Result<T> get() {
|
public Result<T> get() {
|
||||||
final Result<T> result = this.delegate.protectedRun(this.supplier);
|
final Result<T> result = this.delegate.protectedRun(this.supplier);
|
||||||
|
|
|
@ -95,8 +95,6 @@ public interface LmsAPITemplate {
|
||||||
.orElse(Result.ofError(new ResourceNotFoundException(EntityType.EXAM, id)));
|
.orElse(Result.ofError(new ResourceNotFoundException(EntityType.EXAM, id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<QuizData> getQuizFromCache(String id);
|
|
||||||
|
|
||||||
/** Convert a an anonymous or temporary user session identifier from SEB Client into a user
|
/** Convert a an anonymous or temporary user session identifier from SEB Client into a user
|
||||||
* account details.
|
* account details.
|
||||||
*
|
*
|
||||||
|
|
|
@ -43,7 +43,7 @@ public abstract class CourseAccess {
|
||||||
|
|
||||||
protected CourseAccess(final AsyncService asyncService) {
|
protected CourseAccess(final AsyncService asyncService) {
|
||||||
this.allQuizzesRequest = asyncService.createMemoizingCircuitBreaker(
|
this.allQuizzesRequest = asyncService.createMemoizingCircuitBreaker(
|
||||||
allQuizzesSupplier(),
|
allQuizzesSupplier(null),
|
||||||
3,
|
3,
|
||||||
Constants.MINUTE_IN_MILLIS,
|
Constants.MINUTE_IN_MILLIS,
|
||||||
Constants.MINUTE_IN_MILLIS,
|
Constants.MINUTE_IN_MILLIS,
|
||||||
|
@ -66,15 +66,6 @@ public abstract class CourseAccess {
|
||||||
Constants.SECOND_IN_MILLIS * 10);
|
Constants.SECOND_IN_MILLIS * 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Result<QuizData> getQuizFromCache(final String id) {
|
|
||||||
return Result.tryCatch(() -> this.allQuizzesRequest
|
|
||||||
.getCached()
|
|
||||||
.stream()
|
|
||||||
.filter(qd -> id.equals(qd.id))
|
|
||||||
.findFirst()
|
|
||||||
.orElseThrow(() -> new NoSuchElementException("No cached quiz: " + id)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Result<Collection<Result<QuizData>>> getQuizzesFromCache(final Set<String> ids) {
|
public Result<Collection<Result<QuizData>>> getQuizzesFromCache(final Set<String> ids) {
|
||||||
return Result.tryCatch(() -> {
|
return Result.tryCatch(() -> {
|
||||||
final List<QuizData> cached = this.allQuizzesRequest.getCached();
|
final List<QuizData> cached = this.allQuizzesRequest.getCached();
|
||||||
|
@ -109,12 +100,9 @@ public abstract class CourseAccess {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note: this can be overwritten to load missing requested quiz data from specified LMS by id */
|
|
||||||
protected Map<String, QuizData> loadMissingData(final Set<String> ids) {
|
|
||||||
throw new RuntimeException("Not all requested quizzes cached");
|
|
||||||
}
|
|
||||||
|
|
||||||
public Result<List<QuizData>> getQuizzes(final FilterMap filterMap) {
|
public Result<List<QuizData>> getQuizzes(final FilterMap filterMap) {
|
||||||
|
// TODO deal with filter attributes
|
||||||
|
|
||||||
return this.allQuizzesRequest.get()
|
return this.allQuizzesRequest.get()
|
||||||
.map(LmsAPIService.quizzesFilterFunction(filterMap));
|
.map(LmsAPIService.quizzesFilterFunction(filterMap));
|
||||||
}
|
}
|
||||||
|
@ -150,7 +138,7 @@ public abstract class CourseAccess {
|
||||||
|
|
||||||
protected abstract Supplier<List<QuizData>> quizzesSupplier(final Set<String> ids);
|
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);
|
protected abstract Supplier<Chapters> getCourseChaptersSupplier(final String courseId);
|
||||||
|
|
||||||
|
|
|
@ -169,11 +169,6 @@ final class MockupLmsAPITemplate implements LmsAPITemplate {
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Result<QuizData> getQuizFromCache(final String id) {
|
|
||||||
return getQuiz(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Result<QuizData>> getQuizzesFromCache(final Set<String> ids) {
|
public Collection<Result<QuizData>> getQuizzesFromCache(final Set<String> ids) {
|
||||||
return getQuizzes(ids);
|
return getQuizzes(ids);
|
||||||
|
|
|
@ -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.Result;
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||||
import ch.ethz.seb.sebserver.webservice.WebserviceInfo;
|
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;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.CourseAccess;
|
||||||
|
|
||||||
/** Implements the LmsAPITemplate for Open edX LMS Course API access.
|
/** Implements the LmsAPITemplate for Open edX LMS Course API access.
|
||||||
|
@ -173,7 +174,7 @@ final class OpenEdxCourseAccess extends CourseAccess {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Supplier<List<QuizData>> allQuizzesSupplier() {
|
protected Supplier<List<QuizData>> allQuizzesSupplier(final FilterMap filterMap) {
|
||||||
return () -> getRestTemplate()
|
return () -> getRestTemplate()
|
||||||
.map(this::collectAllQuizzes)
|
.map(this::collectAllQuizzes)
|
||||||
.getOrThrow();
|
.getOrThrow();
|
||||||
|
|
|
@ -8,9 +8,7 @@
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.edx;
|
package ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.edx;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -86,13 +84,6 @@ final class OpenEdxLmsAPITemplate implements LmsAPITemplate {
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Result<QuizData> getQuizFromCache(final String id) {
|
|
||||||
return getQuizzesFromCache(new HashSet<>(Arrays.asList(id)))
|
|
||||||
.iterator()
|
|
||||||
.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Result<QuizData>> getQuizzesFromCache(final Set<String> ids) {
|
public Collection<Result<QuizData>> getQuizzesFromCache(final Set<String> ids) {
|
||||||
return this.openEdxCourseAccess.getQuizzesFromCache(ids)
|
return this.openEdxCourseAccess.getQuizzesFromCache(ids)
|
||||||
|
|
|
@ -46,6 +46,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.model.user.ExamineeAccountDetails;
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
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.CourseAccess;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.MoodleRestTemplateFactory.MoodleAPIRestTemplate;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.MoodleRestTemplateFactory.MoodleAPIRestTemplate;
|
||||||
|
|
||||||
|
@ -175,7 +176,7 @@ public class MoodleCourseAccess extends CourseAccess {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Supplier<List<QuizData>> allQuizzesSupplier() {
|
protected Supplier<List<QuizData>> allQuizzesSupplier(final FilterMap filterMap) {
|
||||||
return () -> getRestTemplate()
|
return () -> getRestTemplate()
|
||||||
.map(this::collectAllQuizzes)
|
.map(this::collectAllQuizzes)
|
||||||
.getOrThrow();
|
.getOrThrow();
|
||||||
|
@ -228,9 +229,8 @@ public class MoodleCourseAccess extends CourseAccess {
|
||||||
|
|
||||||
private List<CourseData> getQuizzesBatch(final MoodleAPIRestTemplate restTemplate, final int page) {
|
private List<CourseData> getQuizzesBatch(final MoodleAPIRestTemplate restTemplate, final int page) {
|
||||||
try {
|
try {
|
||||||
// first get courses from Moodle per page
|
// first get courses from Moodle for page
|
||||||
final Map<String, CourseData> courseData = new HashMap<>();
|
final Map<String, CourseData> courseData = new HashMap<>();
|
||||||
|
|
||||||
final Collection<CourseData> coursesPage = getCoursesPage(restTemplate, page, 100);
|
final Collection<CourseData> coursesPage = getCoursesPage(restTemplate, page, 100);
|
||||||
|
|
||||||
if (coursesPage.isEmpty()) {
|
if (coursesPage.isEmpty()) {
|
||||||
|
|
|
@ -90,12 +90,6 @@ public class MoodleLmsAPITemplate implements LmsAPITemplate {
|
||||||
.getOrElse(() -> getQuizzes(ids));
|
.getOrElse(() -> getQuizzes(ids));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Result<QuizData> getQuizFromCache(final String id) {
|
|
||||||
return this.moodleCourseAccess.getQuizFromCache(id)
|
|
||||||
.orElse(() -> getQuiz(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Result<Chapters> getCourseChapters(final String courseId) {
|
public Result<Chapters> getCourseChapters(final String courseId) {
|
||||||
return Result.tryCatch(() -> this.moodleCourseAccess
|
return Result.tryCatch(() -> this.moodleCourseAccess
|
||||||
|
|
Loading…
Reference in a new issue