fixed some bugs in bulk action and moodle load sync

This commit is contained in:
anhefti 2021-01-19 14:55:09 +01:00
parent de760b3714
commit adce16bc7c
5 changed files with 59 additions and 11 deletions

View file

@ -87,6 +87,7 @@ public class BulkActionServiceImpl implements BulkActionService {
@Override @Override
public void collectDependencies(final BulkAction action) { public void collectDependencies(final BulkAction action) {
checkProcessing(action); checkProcessing(action);
updateDependencyTypes(action);
for (final BulkActionSupportDAO<?> sup : this.supporter.values()) { for (final BulkActionSupportDAO<?> sup : this.supporter.values()) {
action.dependencies.addAll(sup.getDependencies(action)); action.dependencies.addAll(sup.getDependencies(action));
} }
@ -107,6 +108,7 @@ public class BulkActionServiceImpl implements BulkActionService {
throw new IllegalArgumentException("No bulk action support for: " + action); throw new IllegalArgumentException("No bulk action support for: " + action);
} }
updateDependencyTypes(action);
collectDependencies(action); collectDependencies(action);
if (!action.dependencies.isEmpty()) { if (!action.dependencies.isEmpty()) {
@ -286,8 +288,15 @@ public class BulkActionServiceImpl implements BulkActionService {
} }
private void checkProcessing(final BulkAction action) { private void checkProcessing(final BulkAction action) {
if (action.alreadyProcessed) {
throw new IllegalStateException("Given BulkAction has already been processed. Use a new one");
}
}
private void updateDependencyTypes(final BulkAction action) {
// complete this.directDependancyMap if needed // complete this.directDependancyMap if needed
if (action.includeDependencies != null) { if (action.includeDependencies != null && !action.includeDependencies.isEmpty()) {
this.directDependancyMap.entrySet().stream() this.directDependancyMap.entrySet().stream()
.forEach(entry -> { .forEach(entry -> {
if (action.includeDependencies.contains(entry.getKey())) { if (action.includeDependencies.contains(entry.getKey())) {
@ -295,9 +304,6 @@ public class BulkActionServiceImpl implements BulkActionService {
} }
}); });
} }
if (action.alreadyProcessed) {
throw new IllegalStateException("Given BulkAction has already been processed. Use a new one");
}
} }
} }

View file

@ -59,6 +59,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ResourceNotFoundException; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ResourceNotFoundException;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.TransactionHandler; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.TransactionHandler;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService; 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.moodle.MoodleCourseAccess; import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.MoodleCourseAccess;
@Lazy @Lazy
@ -791,9 +792,7 @@ public class ExamDAOImpl implements ExamDAO {
// get and map quizzes // get and map quizzes
final Map<String, QuizData> quizzes = this.lmsAPIService final Map<String, QuizData> quizzes = this.lmsAPIService
.getLmsAPITemplate(lmsSetupId) .getLmsAPITemplate(lmsSetupId)
.map(template -> (cached) .map(template -> getQuizzesFromLMS(template, recordMapping.keySet(), cached))
? template.getQuizzesFromCache(recordMapping.keySet())
: template.getQuizzes(recordMapping.keySet()))
.getOrThrow() .getOrThrow()
.stream() .stream()
.flatMap(Result::skipOnError) .flatMap(Result::skipOnError)
@ -814,6 +813,18 @@ public class ExamDAOImpl implements ExamDAO {
}); });
} }
private Collection<Result<QuizData>> getQuizzesFromLMS(final LmsAPITemplate template, final Set<String> ids,
final boolean cached) {
try {
return (cached)
? template.getQuizzesFromCache(ids)
: template.getQuizzes(ids);
} catch (final Exception e) {
log.error("Unexpected error while using LmsAPITemplate to get quizzes: ", e);
return Collections.emptyList();
}
}
private QuizData getQuizData( private QuizData getQuizData(
final Map<String, QuizData> quizzes, final Map<String, QuizData> quizzes,
final String externalId, final String externalId,

View file

@ -147,11 +147,23 @@ public interface LmsAPIService {
return new Page<>(0, 1, sortAttribute, Collections.emptyList()); return new Page<>(0, 1, sortAttribute, Collections.emptyList());
} }
final int start = (pageNumber - 1) * pageSize; int start = (pageNumber - 1) * pageSize;
int end = start + pageSize; int end = start + pageSize;
if (end > quizzes.size()) { if (end > quizzes.size()) {
end = quizzes.size(); end = quizzes.size();
} }
if (start >= end) {
start = end - pageSize;
if (start < 0) {
start = 0;
}
return new Page<>(
(quizzes.size() <= pageSize) ? 1 : quizzes.size() / pageSize + 1,
start / pageSize + 1,
sortAttribute,
quizzes.subList(start, end));
}
return new Page<>( return new Page<>(
(quizzes.size() <= pageSize) ? 1 : quizzes.size() / pageSize + 1, (quizzes.size() <= pageSize) ? 1 : quizzes.size() / pageSize + 1,

View file

@ -273,6 +273,7 @@ public class MoodleCourseAccess extends CourseAccess {
} else if (this.moodleCourseDataAsyncLoader.isLongRunningTask()) { } else if (this.moodleCourseDataAsyncLoader.isLongRunningTask()) {
// on long running tasks if we have a different fromCutTime as before // on long running tasks if we have a different fromCutTime as before
// kick off the lazy loading task immediately with the new time filter // kick off the lazy loading task immediately with the new time filter
courseQuizData = this.moodleCourseDataAsyncLoader.getCachedCourseData();
if (fromCutTime > 0 && fromCutTime != this.moodleCourseDataAsyncLoader.getFromCutTime()) { if (fromCutTime > 0 && fromCutTime != this.moodleCourseDataAsyncLoader.getFromCutTime()) {
this.moodleCourseDataAsyncLoader.setFromCutTime(fromCutTime); this.moodleCourseDataAsyncLoader.setFromCutTime(fromCutTime);
this.moodleCourseDataAsyncLoader.loadAsync(restTemplate); this.moodleCourseDataAsyncLoader.loadAsync(restTemplate);
@ -281,7 +282,7 @@ public class MoodleCourseAccess extends CourseAccess {
* Constants.MINUTE_IN_MILLIS) { * Constants.MINUTE_IN_MILLIS) {
this.moodleCourseDataAsyncLoader.loadAsync(restTemplate); this.moodleCourseDataAsyncLoader.loadAsync(restTemplate);
} }
courseQuizData = this.moodleCourseDataAsyncLoader.getCachedCourseData();
} else { } else {
// just run the task in sync // just run the task in sync
if (fromCutTime >= 0) { if (fromCutTime >= 0) {

View file

@ -64,6 +64,7 @@ public class MoodleCourseDataAsyncLoader {
private final int pageSize; private final int pageSize;
private final Set<CourseDataShort> cachedCourseData = new HashSet<>(); private final Set<CourseDataShort> cachedCourseData = new HashSet<>();
private final Set<String> newIds = new HashSet<>();
private String lmsSetup = Constants.EMPTY_NOTE; private String lmsSetup = Constants.EMPTY_NOTE;
private long lastRunTime = 0; private long lastRunTime = 0;
@ -132,7 +133,7 @@ public class MoodleCourseDataAsyncLoader {
} }
public boolean isLongRunningTask() { public boolean isLongRunningTask() {
return this.lastLoadTime > 30 * Constants.SECOND_IN_MILLIS; return this.lastLoadTime > 3 * Constants.SECOND_IN_MILLIS;
} }
public Set<CourseDataShort> loadSync(final MoodleAPIRestTemplate restTemplate) { public Set<CourseDataShort> loadSync(final MoodleAPIRestTemplate restTemplate) {
@ -167,10 +168,12 @@ public class MoodleCourseDataAsyncLoader {
private Runnable loadAndCache(final MoodleAPIRestTemplate restTemplate) { private Runnable loadAndCache(final MoodleAPIRestTemplate restTemplate) {
return () -> { return () -> {
this.cachedCourseData.clear(); //this.cachedCourseData.clear();
this.newIds.clear();
final long startTime = Utils.getMillisecondsNow(); final long startTime = Utils.getMillisecondsNow();
loadAllQuizzes(restTemplate); loadAllQuizzes(restTemplate);
syncCache();
this.lastLoadTime = Utils.getMillisecondsNow() - startTime; this.lastLoadTime = Utils.getMillisecondsNow() - startTime;
this.running = false; this.running = false;
@ -259,6 +262,7 @@ public class MoodleCourseDataAsyncLoader {
c); c);
} else { } else {
this.cachedCourseData.add(c); this.cachedCourseData.add(c);
this.newIds.add(c.id);
} }
}); });
@ -453,6 +457,20 @@ public class MoodleCourseDataAsyncLoader {
}; };
} }
private void syncCache() {
if (!this.cachedCourseData.isEmpty()) {
final Set<CourseDataShort> newData = this.cachedCourseData.stream()
.filter(data -> this.newIds.contains(data.id))
.collect(Collectors.toSet());
synchronized (this.cachedCourseData) {
this.cachedCourseData.clear();
this.cachedCourseData.addAll(newData);
}
}
this.newIds.clear();
}
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
static final class CoursePage { static final class CoursePage {
final Collection<CourseKey> courseKeys; final Collection<CourseKey> courseKeys;