Refactor code execution to use async functions
This refactoring is required for Sentry tracing. It ensures that the respective functions only return as soon as a code execution finished. With this approach, we can then instrument the duration of the functions, so that Sentry spans are created as desired. Co-authored-by: Jan Graichen <jgraichen@altimos.de>
This commit is contained in:

committed by
Sebastian Serth

parent
c8609e5392
commit
86c67f3c9a
@ -3,7 +3,7 @@ CodeOceanEditorWebsocket = {
|
||||
// Replace `http` with `ws` for the WebSocket connection. This also works with `https` and `wss`.
|
||||
webSocketProtocol: window.location.protocol.replace(/^http/, 'ws').split(':')[0],
|
||||
|
||||
initializeSocket: function(urlHelper, params, closeCallback) {
|
||||
runSocket: function(urlHelper, params, setupFunction) {
|
||||
// 1. Specify the protocol for all URLs to generate
|
||||
params.protocol = this.webSocketProtocol;
|
||||
params._options = true;
|
||||
@ -32,48 +32,73 @@ CodeOceanEditorWebsocket = {
|
||||
|
||||
// 4. Connect to the given URL.
|
||||
this.websocket = new CommandSocket(url,
|
||||
function (evt) {
|
||||
this.resetOutputTab();
|
||||
}.bind(this)
|
||||
function (evt) {
|
||||
this.resetOutputTab();
|
||||
}.bind(this)
|
||||
);
|
||||
|
||||
// Attach custom handlers for messages received.
|
||||
setupFunction(this.websocket);
|
||||
|
||||
CodeOceanEditorWebsocket.websocket = this.websocket;
|
||||
this.websocket.onError(this.showWebsocketError.bind(this));
|
||||
this.websocket.onClose(function(span, callback){
|
||||
span?.finish();
|
||||
if(callback != null){
|
||||
callback();
|
||||
}
|
||||
}.bind(this, span, closeCallback));
|
||||
|
||||
// Create and return a new Promise. It will only resolve (or fail) once the connection has ended.
|
||||
return new Promise((resolve, reject) => {
|
||||
this.websocket.onError(this.showWebsocketError.bind(this));
|
||||
|
||||
// Remove event listeners for Promise handling.
|
||||
// This is especially useful in case of an error, where a `close` event might follow the `error` event.
|
||||
const teardown = () => {
|
||||
this.websocket.websocket.removeEventListener(closeListener);
|
||||
this.websocket.websocket.removeEventListener(errorListener);
|
||||
};
|
||||
|
||||
// We are using event listeners (and not `onError` or `onClose`) here, since these listeners should never be overwritten.
|
||||
// With `onError` or `onClose`, a new assignment would overwrite a previous one.
|
||||
const closeListener = this.websocket.websocket.addEventListener('close', () => {
|
||||
span?.finish();
|
||||
resolve();
|
||||
teardown();
|
||||
});
|
||||
const errorListener = this.websocket.websocket.addEventListener('error', (error) => {
|
||||
reject(error);
|
||||
teardown();
|
||||
this.websocket.killWebSocket(); // In case of error, ensure we always close the connection.
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
initializeSocketForTesting: function(submissionID, filename) {
|
||||
this.initializeSocket(Routes.test_submission_url, {id: submissionID, filename: filename});
|
||||
this.websocket.on('default',this.handleTestResponse.bind(this));
|
||||
this.websocket.on('exit', this.handleExitCommand.bind(this));
|
||||
socketTestCode: function(submissionID, filename) {
|
||||
return this.runSocket(Routes.test_submission_url, {id: submissionID, filename: filename}, (websocket) => {
|
||||
websocket.on('default', this.handleTestResponse.bind(this));
|
||||
websocket.on('exit', this.handleExitCommand.bind(this));
|
||||
});
|
||||
},
|
||||
|
||||
initializeSocketForScoring: function(submissionID) {
|
||||
this.initializeSocket(Routes.score_submission_url, {id: submissionID}, function() {
|
||||
$('#assess').one('click', this.scoreCode.bind(this))
|
||||
}.bind(this));
|
||||
this.websocket.on('default',this.handleScoringResponse.bind(this));
|
||||
this.websocket.on('hint', this.showHint.bind(this));
|
||||
this.websocket.on('exit', this.handleExitCommand.bind(this));
|
||||
this.websocket.on('status', this.showStatus.bind(this));
|
||||
socketScoreCode: function(submissionID) {
|
||||
return this.runSocket(Routes.score_submission_url, {id: submissionID}, (websocket) => {
|
||||
websocket.on('default', this.handleScoringResponse.bind(this));
|
||||
websocket.on('hint', this.showHint.bind(this));
|
||||
websocket.on('exit', this.handleExitCommand.bind(this));
|
||||
websocket.on('status', this.showStatus.bind(this));
|
||||
}).then(() => {
|
||||
$('#assess').one('click', this.scoreCode.bind(this));
|
||||
});
|
||||
},
|
||||
|
||||
initializeSocketForRunning: function(submissionID, filename) {
|
||||
this.initializeSocket(Routes.run_submission_url, {id: submissionID, filename: filename});
|
||||
this.websocket.on('input',this.showPrompt.bind(this));
|
||||
this.websocket.on('write', this.printWebsocketOutput.bind(this));
|
||||
this.websocket.on('clear', this.clearOutput.bind(this));
|
||||
this.websocket.on('turtle', this.handleTurtleCommand.bind(this));
|
||||
this.websocket.on('turtlebatch', this.handleTurtlebatchCommand.bind(this));
|
||||
this.websocket.on('render', this.printWebsocketOutput.bind(this));
|
||||
this.websocket.on('exit', this.handleExitCommand.bind(this));
|
||||
this.websocket.on('status', this.showStatus.bind(this));
|
||||
this.websocket.on('hint', this.showHint.bind(this));
|
||||
this.websocket.on('files', this.prepareFileDownloads.bind(this));
|
||||
socketRunCode: function(submissionID, filename) {
|
||||
return this.runSocket(Routes.run_submission_url, {id: submissionID, filename: filename}, (websocket) => {
|
||||
websocket.on('input', this.showPrompt.bind(this));
|
||||
websocket.on('write', this.printWebsocketOutput.bind(this));
|
||||
websocket.on('clear', this.clearOutput.bind(this));
|
||||
websocket.on('turtle', this.handleTurtleCommand.bind(this));
|
||||
websocket.on('turtlebatch', this.handleTurtlebatchCommand.bind(this));
|
||||
websocket.on('render', this.printWebsocketOutput.bind(this));
|
||||
websocket.on('exit', this.handleExitCommand.bind(this));
|
||||
websocket.on('status', this.showStatus.bind(this));
|
||||
websocket.on('hint', this.showHint.bind(this));
|
||||
websocket.on('files', this.prepareFileDownloads.bind(this));
|
||||
});
|
||||
},
|
||||
|
||||
handleExitCommand: function() {
|
||||
|
Reference in New Issue
Block a user