diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/SEBServerMigrationStrategy.java b/src/main/java/ch/ethz/seb/sebserver/webservice/SEBServerMigrationStrategy.java index a97b3393..1cd1a8ab 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/SEBServerMigrationStrategy.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/SEBServerMigrationStrategy.java @@ -9,12 +9,15 @@ package ch.ethz.seb.sebserver.webservice; import org.flywaydb.core.Flyway; +import org.flywaydb.core.api.MigrationInfo; +import org.flywaydb.core.api.MigrationInfoService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.flyway.FlywayMigrationStrategy; import org.springframework.stereotype.Component; +import ch.ethz.seb.sebserver.SEBServerInit; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.WebserviceInfoDAO; @@ -27,6 +30,8 @@ public class SEBServerMigrationStrategy implements FlywayMigrationStrategy { private final boolean cleanDBOnStartup; private final WebserviceInfo webserviceInfo; private final WebserviceInfoDAO webserviceInfoDAO; + private Flyway flyway; + private final boolean migrationApplied = false; public SEBServerMigrationStrategy( final WebserviceInfo webserviceInfo, @@ -40,31 +45,83 @@ public class SEBServerMigrationStrategy implements FlywayMigrationStrategy { @Override public void migrate(final Flyway flyway) { + this.flyway = flyway; + + } + + public void applyMigration() { + final String webserviceUUID = this.webserviceInfo.getWebserviceUUID(); + if (this.migrationApplied) { + log.warn("Migration already applied for this webservice: {}", webserviceUUID); + return; + } + try { - // If we are in a distributed setup only apply migration task if this is the master service - // or if there was no data base initialization yet at all. - if (this.webserviceInfo.isDistributed()) { - if (this.webserviceInfoDAO.isInitialized()) { - final boolean isMaster = this.webserviceInfoDAO.isMaster(this.webserviceInfo.getWebserviceUUID()); - if (!isMaster) { - log.info( - "Skip migration task since this is not a master instance: {}", - this.webserviceInfo.getWebserviceUUID()); + SEBServerInit.INIT_LOGGER.info("----> ** Migration check START **"); + SEBServerInit.INIT_LOGGER.info("----> Check database status"); - return; + final MigrationInfoService info = this.flyway.info(); + if (SEBServerInit.INIT_LOGGER.isDebugEnabled()) { + SEBServerInit.INIT_LOGGER.debug("----> ** Migration Info **"); + SEBServerInit.INIT_LOGGER.debug("----> {}", info); + } + + final MigrationInfo[] pendingMigrations = info.pending(); + if (pendingMigrations != null && pendingMigrations.length > 0) { + + SEBServerInit.INIT_LOGGER.info("----> Found pending migrations: {}", pendingMigrations.length); + // If we are in a distributed setup only apply migration task if this is the master service + // or if there was no data base initialization yet at all. + if (this.webserviceInfo.isDistributed()) { + + SEBServerInit.INIT_LOGGER.info("----> This is distributed setup, check master..."); + + if (this.webserviceInfoDAO.isInitialized()) { + final boolean isMaster = this.webserviceInfoDAO.isMaster(webserviceUUID); + if (!isMaster) { + SEBServerInit.INIT_LOGGER.info( + "----> Skip migration task since this is not a master instance: {}", + this.webserviceInfo.getWebserviceUUID()); + } else { + doMigration(); + } } + } else { + doMigration(); } + + } else { + SEBServerInit.INIT_LOGGER.info("----> "); + SEBServerInit.INIT_LOGGER.info("----> No pending migrations found. Last migration --> {} --> {}", + info.current().getVersion(), + info.current().getDescription()); } - if (this.cleanDBOnStartup) { - flyway.clean(); - } - flyway.migrate(); - + SEBServerInit.INIT_LOGGER.info("----> ** Migration check END **"); } catch (final Exception e) { log.error("Failed to apply migration task: ", e); } } + private void doMigration() { + + SEBServerInit.INIT_LOGGER.info("----> *** Start migration ***"); + + if (this.cleanDBOnStartup) { + + SEBServerInit.INIT_LOGGER + .info("----> !!! Cleanup database as it was set on sebserver.webservice.clean-db-on-startup !!!"); + + this.flyway.clean(); + } + this.flyway.migrate(); + + final MigrationInfoService info = this.flyway.info(); + SEBServerInit.INIT_LOGGER.info("----> Migration finished, new current version is: {} --> {}", + info.current().getVersion(), + info.current().getDescription()); + SEBServerInit.INIT_LOGGER.info("----> *** End migration ***"); + } + } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/WebserviceInit.java b/src/main/java/ch/ethz/seb/sebserver/webservice/WebserviceInit.java index b5964ad1..03043afe 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/WebserviceInit.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/WebserviceInit.java @@ -40,6 +40,7 @@ public class WebserviceInit implements ApplicationListener Failed to register webservice: ", e); } + // Apply migration if needed and possible + SEBServerInit.INIT_LOGGER.info("----> "); + this.sebServerMigrationStrategy.applyMigration(); + SEBServerInit.INIT_LOGGER.info("----> "); + SEBServerInit.INIT_LOGGER.info("----> "); SEBServerInit.INIT_LOGGER.info("----> Initialize Services..."); SEBServerInit.INIT_LOGGER.info("----> "); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/WebserviceInfoDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/WebserviceInfoDAOImpl.java index cc452b89..b2d09865 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/WebserviceInfoDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/WebserviceInfoDAOImpl.java @@ -119,8 +119,7 @@ public class WebserviceInfoDAOImpl implements WebserviceInfoDAO { final long now = Utils.getMillisecondsNow(); final long lastUpdateSince = now - masterRec.getUpdateTime(); if (lastUpdateSince > this.masterDelayTimeThreshold || this.forceMaster) { - forceMaster(uuid, masterRec.getUuid(), masterRec.getId()); - return true; + return forceMaster(uuid, masterRec.getUuid(), masterRec.getId()); } } } else { @@ -136,13 +135,14 @@ public class WebserviceInfoDAOImpl implements WebserviceInfoDAO { } } - private void forceMaster(final String uuid, final String otherUUID, final Long otherId) { + private boolean forceMaster(final String uuid, final String otherUUID, final Long otherId) { - log.info("Change webservice master form uuid: {} to uuid: {}", otherUUID, uuid); + log.info("Change webservice master from uuid: {} to uuid: {}", otherUUID, uuid); this.webserviceServerInfoRecordMapper.updateByPrimaryKeySelective( new WebserviceServerInfoRecord(otherId, null, null, 0, 0L)); - setMasterTo(uuid); + + return setMasterTo(uuid); } private boolean setMasterTo(final String uuid) { @@ -156,9 +156,7 @@ public class WebserviceInfoDAOImpl implements WebserviceInfoDAO { .execute(); if (entries == null || entries.isEmpty()) { - if (log.isDebugEnabled()) { - log.debug("The webservice with uuid: {} is not registered and cannot become a master", uuid); - } + log.warn("The webservice with uuid: {} is not registered and cannot become a master", uuid); return false; } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ExamSessionControlTask.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ExamSessionControlTask.java index 9f5fa5f8..af093b3f 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ExamSessionControlTask.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ExamSessionControlTask.java @@ -88,10 +88,11 @@ class ExamSessionControlTask implements DisposableBean { SEBServerInit.INIT_LOGGER.info( "------> Activate SEB lost-ping-event update background task on a fix rate of: {} milliseconds", this.pingUpdateRate); - } - @Scheduled(cron = "${sebserver.webservice.api.exam.update-interval:1 * * * * *}") + @Scheduled( + fixedDelayString = "${sebserver.webservice.api.exam.update-interval:60000}", + initialDelay = 30000) public void examRunUpdateTask() { if (!this.webserviceInfoDAO.isMaster(this.webserviceInfo.getWebserviceUUID())) { @@ -109,7 +110,9 @@ class ExamSessionControlTask implements DisposableBean { this.examDAO.releaseAgedLocks(); } - @Scheduled(fixedDelayString = "${sebserver.webservice.api.seb.lostping.update:5000}") + @Scheduled( + fixedDelayString = "${sebserver.webservice.api.seb.lostping.update:5000}", + initialDelay = 30000) public void examSessionUpdateTask() { this.sebClientConnectionService.updatePingEvents(); @@ -122,7 +125,9 @@ class ExamSessionControlTask implements DisposableBean { this.examProcotringRoomService.updateProctoringCollectingRooms(); } - @Scheduled(fixedRateString = "${sebserver.webservice.api.exam.session-cleanup:30000}") + @Scheduled( + fixedRateString = "${sebserver.webservice.api.exam.session-cleanup:30000}", + initialDelay = 30000) public void examSessionCleanupTask() { if (!this.webserviceInfoDAO.isMaster(this.webserviceInfo.getWebserviceUUID())) { diff --git a/src/main/resources/config/application-dev-ws.properties b/src/main/resources/config/application-dev-ws.properties index 5f2936be..1ba4288f 100644 --- a/src/main/resources/config/application-dev-ws.properties +++ b/src/main/resources/config/application-dev-ws.properties @@ -25,8 +25,8 @@ sebserver.webservice.clean-db-on-startup=false # webservice configuration sebserver.init.adminaccount.gen-on-init=false -sebserver.webservice.distributed=true -sebserver.webservice.master.delay.threshold=10000 +sebserver.webservice.distributed=false +#sebserver.webservice.master.delay.threshold=10000 sebserver.webservice.http.external.scheme=http sebserver.webservice.http.external.servername=localhost sebserver.webservice.http.external.port=${server.port} diff --git a/src/main/resources/config/application-dev.properties b/src/main/resources/config/application-dev.properties index 250767d0..08615890 100644 --- a/src/main/resources/config/application-dev.properties +++ b/src/main/resources/config/application-dev.properties @@ -7,6 +7,7 @@ server.port=8080 server.servlet.context-path=/ server.tomcat.uri-encoding=UTF-8 +logging.level.ROOT=INFO logging.level.ch=INFO logging.level.ch.ethz.seb.sebserver.webservice.datalayer=INFO logging.level.org.springframework.cache=INFO @@ -19,7 +20,7 @@ logging.level.ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicat #logging.level.ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper=DEBUG #logging.level.ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ExamRecordMapper=DEBUG #logging.level.ch.ethz.seb.sebserver.webservice.weblayer.api.ExamAPI_V1_Controller=TRACE -logging.level.com.zaxxer.hikari=DEBUG +logging.level.com.zaxxer.hikari=INFO sebserver.http.client.connect-timeout=15000 sebserver.http.client.connection-request-timeout=10000