Merge remote-tracking branch 'origin/patch-1.0.2' into development
Conflicts: src/main/java/ch/ethz/seb/sebserver/gui/content/MonitoringRunningExam.java
This commit is contained in:
commit
3b1641994a
6 changed files with 108 additions and 42 deletions
|
@ -196,7 +196,10 @@ public class MonitoringClientConnection implements TemplateComposer {
|
||||||
indicators);
|
indicators);
|
||||||
|
|
||||||
this.serverPushService.runServerPush(
|
this.serverPushService.runServerPush(
|
||||||
new ServerPushContext(content, Utils.truePredicate()),
|
new ServerPushContext(
|
||||||
|
content,
|
||||||
|
Utils.truePredicate(),
|
||||||
|
MonitoringRunningExam.createServerPushUpdateErrorHandler(this.pageService, pageContext)),
|
||||||
this.pollInterval,
|
this.pollInterval,
|
||||||
context1 -> clientConnectionDetails.updateData(),
|
context1 -> clientConnectionDetails.updateData(),
|
||||||
context -> clientConnectionDetails.updateGUI());
|
context -> clientConnectionDetails.updateGUI());
|
||||||
|
|
|
@ -26,6 +26,7 @@ import org.eclipse.swt.layout.GridData;
|
||||||
import org.eclipse.swt.layout.GridLayout;
|
import org.eclipse.swt.layout.GridLayout;
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
import org.eclipse.swt.widgets.Display;
|
import org.eclipse.swt.widgets.Display;
|
||||||
|
import org.eclipse.swt.widgets.MessageBox;
|
||||||
import org.eclipse.swt.widgets.Tree;
|
import org.eclipse.swt.widgets.Tree;
|
||||||
import org.eclipse.swt.widgets.TreeItem;
|
import org.eclipse.swt.widgets.TreeItem;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -80,6 +81,7 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
|
||||||
import ch.ethz.seb.sebserver.gui.service.session.ClientConnectionTable;
|
import ch.ethz.seb.sebserver.gui.service.session.ClientConnectionTable;
|
||||||
import ch.ethz.seb.sebserver.gui.service.session.InstructionProcessor;
|
import ch.ethz.seb.sebserver.gui.service.session.InstructionProcessor;
|
||||||
import ch.ethz.seb.sebserver.gui.service.session.ProctoringGUIService;
|
import ch.ethz.seb.sebserver.gui.service.session.ProctoringGUIService;
|
||||||
|
import ch.ethz.seb.sebserver.gui.widget.Message;
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
@Component
|
@Component
|
||||||
|
@ -198,7 +200,9 @@ public class MonitoringRunningExam implements TemplateComposer {
|
||||||
ActionDefinition.MONITOR_EXAM_NEW_PROCTOR_ROOM));
|
ActionDefinition.MONITOR_EXAM_NEW_PROCTOR_ROOM));
|
||||||
|
|
||||||
this.serverPushService.runServerPush(
|
this.serverPushService.runServerPush(
|
||||||
new ServerPushContext(content, Utils.truePredicate()),
|
new ServerPushContext(
|
||||||
|
content, Utils.truePredicate(),
|
||||||
|
createServerPushUpdateErrorHandler(this.pageService, pageContext)),
|
||||||
this.pollInterval,
|
this.pollInterval,
|
||||||
context -> clientTable.updateValues(),
|
context -> clientTable.updateValues(),
|
||||||
updateTableGUI(clientTable));
|
updateTableGUI(clientTable));
|
||||||
|
@ -358,7 +362,10 @@ public class MonitoringRunningExam implements TemplateComposer {
|
||||||
actionBuilder,
|
actionBuilder,
|
||||||
proctoringSettings);
|
proctoringSettings);
|
||||||
this.serverPushService.runServerPush(
|
this.serverPushService.runServerPush(
|
||||||
new ServerPushContext(content, Utils.truePredicate()),
|
new ServerPushContext(
|
||||||
|
content,
|
||||||
|
Utils.truePredicate(),
|
||||||
|
createServerPushUpdateErrorHandler(this.pageService, pageContext)),
|
||||||
this.proctoringRoomUpdateInterval,
|
this.proctoringRoomUpdateInterval,
|
||||||
context -> updateRoomActions(
|
context -> updateRoomActions(
|
||||||
entityKey,
|
entityKey,
|
||||||
|
@ -707,4 +714,30 @@ public class MonitoringRunningExam implements TemplateComposer {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static final Function<Exception, Boolean> createServerPushUpdateErrorHandler(
|
||||||
|
final PageService pageService,
|
||||||
|
final PageContext pageContext) {
|
||||||
|
|
||||||
|
return error -> {
|
||||||
|
log.error("Fialed to update server push: {}", error.getMessage());
|
||||||
|
try {
|
||||||
|
pageService.getCurrentUser().get();
|
||||||
|
} catch (final Exception e) {
|
||||||
|
log.error("Failed to verify current user after server push error: {}", e.getMessage());
|
||||||
|
log.info("Force logout and session cleanup...");
|
||||||
|
pageContext.forwardToLoginPage();
|
||||||
|
final MessageBox logoutSuccess = new Message(
|
||||||
|
pageContext.getShell(),
|
||||||
|
pageService.getI18nSupport().getText("sebserver.logout"),
|
||||||
|
Utils.formatLineBreaks(
|
||||||
|
pageService.getI18nSupport().getText("sebserver.logout.invalid-session.message")),
|
||||||
|
SWT.ICON_INFORMATION,
|
||||||
|
pageService.getI18nSupport());
|
||||||
|
logoutSuccess.open(null);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.gui.service.push;
|
package ch.ethz.seb.sebserver.gui.service.push;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
@ -18,23 +19,25 @@ import org.eclipse.swt.widgets.Display;
|
||||||
* @author anhefti */
|
* @author anhefti */
|
||||||
public final class ServerPushContext {
|
public final class ServerPushContext {
|
||||||
|
|
||||||
private final Composite anchor;
|
public final Composite anchor;
|
||||||
private final Predicate<ServerPushContext> runAgain;
|
public final Predicate<ServerPushContext> runAgain;
|
||||||
|
public final Function<Exception, Boolean> errorHandler;
|
||||||
public ServerPushContext(final Composite anchor) {
|
boolean internalStop = false;
|
||||||
this(anchor, context -> false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ServerPushContext(
|
public ServerPushContext(
|
||||||
final Composite anchor,
|
final Composite anchor,
|
||||||
final Predicate<ServerPushContext> runAgain) {
|
final Predicate<ServerPushContext> runAgain,
|
||||||
|
final Function<Exception, Boolean> errorHandler) {
|
||||||
|
|
||||||
|
this.errorHandler = errorHandler != null
|
||||||
|
? errorHandler
|
||||||
|
: error -> true;
|
||||||
this.anchor = anchor;
|
this.anchor = anchor;
|
||||||
this.runAgain = runAgain;
|
this.runAgain = runAgain;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean runAgain() {
|
public boolean runAgain() {
|
||||||
return this.runAgain.test(this);
|
return !this.internalStop && this.runAgain.test(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDisposed() {
|
public boolean isDisposed() {
|
||||||
|
|
|
@ -54,43 +54,43 @@ public class ServerPushService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (business != null) {
|
if (context.isDisposed()) {
|
||||||
try {
|
continue;
|
||||||
log.trace("Call business on Server Push Session on: {}", Thread.currentThread().getName());
|
|
||||||
business.accept(context);
|
|
||||||
} catch (final Exception e) {
|
|
||||||
log.error("Unexpected error while do business for server push service", e);
|
|
||||||
if (context.runAgain()) {
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!context.isDisposed()) {
|
context.getDisplay().asyncExec(() -> {
|
||||||
|
if (business != null) {
|
||||||
log.trace("Call update on Server Push Session on: {}", Thread.currentThread().getName());
|
|
||||||
|
|
||||||
context.getDisplay().asyncExec(() -> {
|
|
||||||
try {
|
try {
|
||||||
update.accept(context);
|
|
||||||
|
if (log.isTraceEnabled()) {
|
||||||
|
log.trace("Call business on Server Push Session on: {}",
|
||||||
|
Thread.currentThread().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
business.accept(context);
|
||||||
|
doUpdate(context, update);
|
||||||
|
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
log.warn(
|
log.error("Unexpected error while do business for server push service", e);
|
||||||
"Failed to update on Server Push Session {}. It seems that the UISession is not available anymore. "
|
context.internalStop = context.errorHandler.apply(e);
|
||||||
+ "This may source from a connection interruption. cause: {}",
|
|
||||||
Thread.currentThread().getName(), e.getMessage());
|
|
||||||
}
|
}
|
||||||
});
|
} else {
|
||||||
}
|
doUpdate(context, update);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (log.isInfoEnabled()) {
|
||||||
|
log.info("Stop Server Push Session on: {}", Thread.currentThread().getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info("Stop Server Push Session on: {}", Thread.currentThread().getName());
|
|
||||||
try {
|
try {
|
||||||
pushSession.stop();
|
pushSession.stop();
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
log.warn(
|
log.warn(
|
||||||
"Failed to stop Server Push Session on: {}. It seems that the UISession is not available anymore. This may source from a connection interruption",
|
"Failed to stop Server Push Session on: {}. "
|
||||||
|
+ "It seems that the UISession is not available anymore. "
|
||||||
|
+ "This may source from a connection interruption",
|
||||||
Thread.currentThread().getName(), e);
|
Thread.currentThread().getName(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,4 +101,28 @@ public class ServerPushService {
|
||||||
bgThread.setDaemon(true);
|
bgThread.setDaemon(true);
|
||||||
bgThread.start();
|
bgThread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void doUpdate(
|
||||||
|
final ServerPushContext context,
|
||||||
|
final Consumer<ServerPushContext> update) {
|
||||||
|
|
||||||
|
if (!context.isDisposed()) {
|
||||||
|
|
||||||
|
if (log.isTraceEnabled()) {
|
||||||
|
log.trace("Call update on Server Push Session on: {}",
|
||||||
|
Thread.currentThread().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
update.accept(context);
|
||||||
|
} catch (final Exception e) {
|
||||||
|
log.warn(
|
||||||
|
"Failed to update on Server Push Session {}. "
|
||||||
|
+ "It seems that the UISession is not available anymore. "
|
||||||
|
+ "This may source from a connection interruption. cause: {}",
|
||||||
|
Thread.currentThread().getName(), e.getMessage());
|
||||||
|
context.internalStop = context.errorHandler.apply(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -303,10 +303,7 @@ public final class ClientConnectionTable {
|
||||||
this.restCallBuilder
|
this.restCallBuilder
|
||||||
.withHeader(API.EXAM_MONITORING_STATE_FILTER, this.statusFilterParam)
|
.withHeader(API.EXAM_MONITORING_STATE_FILTER, this.statusFilterParam)
|
||||||
.call()
|
.call()
|
||||||
.get(error -> {
|
.getOrThrow()
|
||||||
log.error("Error poll connection data: ", error);
|
|
||||||
return Collections.emptyList();
|
|
||||||
})
|
|
||||||
.forEach(data -> {
|
.forEach(data -> {
|
||||||
final UpdatableTableItem tableItem = this.tableMapping.computeIfAbsent(
|
final UpdatableTableItem tableItem = this.tableMapping.computeIfAbsent(
|
||||||
data.getConnectionId(),
|
data.getConnectionId(),
|
||||||
|
|
|
@ -113,7 +113,13 @@ public final class ImageUploadSelection extends Composite {
|
||||||
ImageUploadSelection.this.fileUpload.submit(uploadHandler.getUploadUrl());
|
ImageUploadSelection.this.fileUpload.submit(uploadHandler.getUploadUrl());
|
||||||
|
|
||||||
ImageUploadSelection.this.serverPushService.runServerPush(
|
ImageUploadSelection.this.serverPushService.runServerPush(
|
||||||
new ServerPushContext(ImageUploadSelection.this, ImageUploadSelection::uploadInProgress),
|
new ServerPushContext(
|
||||||
|
ImageUploadSelection.this,
|
||||||
|
ImageUploadSelection::uploadInProgress,
|
||||||
|
error -> {
|
||||||
|
log.error("Failed to upload image: {}", error.getMessage());
|
||||||
|
return false;
|
||||||
|
}),
|
||||||
200,
|
200,
|
||||||
ImageUploadSelection::update);
|
ImageUploadSelection::update);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue