From cc60ad374ee9ccca98533ce8ab44ee74c7f0fb2e Mon Sep 17 00:00:00 2001 From: osmala <ossi.laine@utu.fi> Date: Wed, 10 Jun 2020 10:37:00 +0300 Subject: [PATCH] Error handling --- .../templates/experiment_statistics.html | 3 +- app/experiment/views.py | 51 ++++++++++--------- app/static/css/main.css | 5 ++ app/static/js/getCSV.js | 10 +++- app/utils.py | 12 +++-- 5 files changed, 50 insertions(+), 31 deletions(-) diff --git a/app/experiment/templates/experiment_statistics.html b/app/experiment/templates/experiment_statistics.html index 2dd5a34..2054314 100644 --- a/app/experiment/templates/experiment_statistics.html +++ b/app/experiment/templates/experiment_statistics.html @@ -45,7 +45,8 @@ </button> <div id="export-link-container" class="hidden"> - <a id="export-link" class="float-right" href="{{ url_for('experiment.download_csv', exp_id=exp.idexperiment) }}" role="button">Download</a> + <a id="export-link" class="float-right" href="{{ url_for('experiment.download_csv', exp_id=exp.idexperiment) }}" role="button"></a> + <p id="export-error"></p> </div> diff --git a/app/experiment/views.py b/app/experiment/views.py index 462db81..623b1fc 100644 --- a/app/experiment/views.py +++ b/app/experiment/views.py @@ -1015,8 +1015,27 @@ def statistics(): finished_ratings=finished_ratings, question_headers=question_headers, stimulus_headers=stimulus_headers, - embody_questions=embody_questions - ) + embody_questions=embody_questions) + + +@experiment_blueprint.route('/download_csv') +def download_csv(): + exp_id = request.args.get('exp_id', None) + path = request.args.get('path', None) + + filename = "experiment_{}_{}.csv".format( + exp_id, date.today().strftime("%Y-%m-%d")) + + path = '/tmp/' + path + + try: + return send_file(path, + mimetype='text/csv', + as_attachment=True, + attachment_filename=filename) + + finally: + os.remove(path) def remove_rows(rows): @@ -1061,10 +1080,11 @@ def create_embody(meta): exp_id = meta["exp_id"] - csv = generate_csv(exp_id) + data = generate_csv(exp_id) - if not csv: - emit('timeout') + if isinstance(data, Exception): + emit('timeout', {'exc': str(data)}) + return filename = "experiment_{}_{}".format( exp_id, date.today().strftime("%Y-%m-%d")) @@ -1075,7 +1095,7 @@ def create_embody(meta): print(path) with os.fdopen(fd, 'w') as tmp: - tmp.write(csv) + tmp.write(data) tmp.flush() path = path.split('/')[-1] @@ -1084,22 +1104,3 @@ def create_embody(meta): # return saved_data_as_file(filename, csv) - -@experiment_blueprint.route('/download_csv') -def download_csv(): - exp_id = request.args.get('exp_id', None) - path = request.args.get('path', None) - - filename = "experiment_{}_{}.csv".format( - exp_id, date.today().strftime("%Y-%m-%d")) - - path = '/tmp/' + path - - try: - return send_file(path, - mimetype='text/csv', - as_attachment=True, - attachment_filename=filename) - - finally: - os.remove(path) diff --git a/app/static/css/main.css b/app/static/css/main.css index 7267759..f0c53e7 100644 --- a/app/static/css/main.css +++ b/app/static/css/main.css @@ -82,3 +82,8 @@ body { margin-top: 20px; padding: 10px; } + +#export-error { + float:right; + color:red; +} diff --git a/app/static/js/getCSV.js b/app/static/js/getCSV.js index 81243a3..a2d3463 100644 --- a/app/static/js/getCSV.js +++ b/app/static/js/getCSV.js @@ -10,6 +10,7 @@ $(document).ready(function() { var exportLinkContainer = $("#export-link-container"); var exportLink = $("#export-link"); + var exportError = $("#export-error"); // With sockets function initConnection(socket) { @@ -20,12 +21,19 @@ $(document).ready(function() { }); socket.on('progress', function(data) { + console.log(data) progressBar.width(100*(data.done/data.from) + '%') }); socket.on('timeout', function(data) { - console.log("timeout error", data) + console.log("timeout error", data.exc) socket.disconnect() + exportButton.text('Export results') + exportButton.removeClass('disabled') + progressBarContainer.addClass("hidden") + + exportLinkContainer.removeClass("hidden") + exportError.text('Error: ' + data.exc) }); socket.on('file_ready', function(file) { diff --git a/app/utils.py b/app/utils.py index a36b220..ebf43e4 100644 --- a/app/utils.py +++ b/app/utils.py @@ -1,9 +1,11 @@ import os import tempfile import time +import json from itertools import zip_longest import concurrent.futures from flask import send_file +from flask_socketio import emit from app import app from app.models import background_question, background_question_answer, \ page, question, answer_set, answer, embody_answer, embody_question @@ -99,7 +101,7 @@ def map_answers_to_questions(answers, questions): break if question_matches_answer(question, current_answer): - results[nth_question] = current_answer.result + results[nth_question] = current_answer.result() nth_answer += 1 return results @@ -184,6 +186,8 @@ def generate_csv(exp_id): participants = list(filter(lambda participant: True if int( participant.answer_counter) > 0 else False, participants)) + len_participants = len(participants) + # We can use a with statement to ensure threads are cleaned up promptly with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: # Start the load operations and mark each future with its URL @@ -191,16 +195,16 @@ def generate_csv(exp_id): executor.submit(generate_answer_row, participant, pages, questions, embody_questions): participant for participant in participants} - for future in concurrent.futures.as_completed(future_to_answer): + for nth, future in enumerate(concurrent.futures.as_completed(future_to_answer)): # for testing purpose # answer_row = future_to_answer[future] try: + emit('progress', {'done': nth, 'from': len_participants}) data = future.result() csv += data + '\r\n' - except TimeoutError: - return None except Exception as exc: print('generated an exception: {}'.format(exc)) + return exc return csv -- GitLab