added update task to release aged exam record locks

This commit is contained in:
anhefti 2021-08-05 10:54:28 +02:00
parent 9a9ad6e840
commit 76a1676b69
6 changed files with 42 additions and 4 deletions

View file

@ -128,6 +128,9 @@ public interface ExamDAO extends ActivatableEntityDAO<Exam, Exam>, BulkActionSup
* @return Result refer to the lock-check-result or to an error if happened */
Result<Boolean> isLocked(Long examId);
/** This checks if there are write locks that are out of date and release such. */
void releaseAgedLocks();
/** Use this to check if the exam with the specified identifier is up to date
*
* @param examId the exam identifier

View file

@ -574,7 +574,8 @@ public class ExamDAOImpl implements ExamDAO {
}
return Result.tryCatch(() -> {
final Collection<Long> result = this.examRecordMapper.selectIdsByExample()
final Collection<Long> result = this.examRecordMapper
.selectIdsByExample()
.where(ExamRecordDynamicSqlSupport.lastupdate, isEqualTo(updateId))
.build()
.execute()
@ -596,6 +597,39 @@ public class ExamDAOImpl implements ExamDAO {
.map(rec -> BooleanUtils.toBooleanObject(rec.getUpdating()));
}
@Override
@Transactional
public void releaseAgedLocks() {
try {
final List<ExamRecord> lockedRecords = this.examRecordMapper
.selectByExample()
.where(ExamRecordDynamicSqlSupport.updating, isNotEqualTo(0))
.build()
.execute();
if (lockedRecords != null && !lockedRecords.isEmpty()) {
final long millisecondsNow = Utils.getMillisecondsNow();
lockedRecords.stream().forEach(record -> {
try {
final String lastUpdateString = record.getLastupdate();
if (StringUtils.isNotBlank(lastUpdateString)) {
final String[] split = StringUtils.split(lastUpdateString, Constants.UNDERLINE);
final long timestamp = Long.parseLong(split[2]);
if (millisecondsNow - timestamp > Constants.MINUTE_IN_MILLIS) {
forceUnlock(record.getId()).getOrThrow();
}
}
} catch (final Exception e) {
log.warn("Failed to release aged write lock for exam: {} cause:", record, e.getMessage());
}
});
}
} catch (final Exception e) {
log.error("Failed to release aged write locks: {}", e.getMessage());
}
}
@Override
@Transactional(readOnly = true)
public Result<Boolean> upToDate(final Long examId, final String updateId) {

View file

@ -108,7 +108,7 @@ public class WebserviceInfoDAOImpl implements WebserviceInfoDAO {
new WebserviceServerInfoRecord(masterRec.getId(), null, null, null, now));
if (log.isDebugEnabled()) {
log.debug("Update master webservice {} time: {}", uuid, now);
log.trace("Update master webservice {} time: {}", uuid, now);
}
return true;

View file

@ -106,6 +106,7 @@ class ExamSessionControlTask implements DisposableBean {
controlExamStart(updateId);
controlExamEnd(updateId);
this.examDAO.releaseAgedLocks();
}
@Scheduled(fixedRateString = "${sebserver.webservice.api.seb.lostping.update:5000}")

View file

@ -7,7 +7,8 @@ server.port=8080
server.servlet.context-path=/
server.tomcat.uri-encoding=UTF-8
logging.level.ch=INFO
logging.level.ch=DEBUG
logging.level.ch.ethz.seb.sebserver.webservice.datalayer=INFO
logging.level.org.springframework.cache=INFO
logging.level.ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl=DEBUG
logging.level.ch.ethz.seb.sebserver.webservice.servicelayer.session=DEBUG

View file

@ -19,7 +19,6 @@
<root level="INFO" additivity="true">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
<Logger name="ch.ethz.seb.SEB_SERVER_INIT" level="INFO" additivity="false">
<appender-ref ref="STDOUT" />