Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 32 additions & 2 deletions portal/models/questionnaire_response.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import csv
import tempfile
from collections import defaultdict, namedtuple
import copy
import csv
from datetime import datetime
from dateutil.relativedelta import relativedelta
from html.parser import HTMLParser
import json
import os
import tempfile
import time

from flask import current_app, has_request_context, url_for
from flask_swagger import swagger
Expand Down Expand Up @@ -943,6 +945,34 @@ def aggregate_responses(
return filepath


def report_dir_janitor():
"""Purge old reports to avoid filling disk

Intended to be called by a scheduled job, removes stale reports from
configured TMP_REPORT_DIR
"""
report_dir = current_app.config['TMP_REPORT_DIR']
if not(os.path.exists(report_dir)):
current_app.logger.warning("configured TMP_REPORT_DIR not found")
return

days_to_keep = 7
cutoff = time.time() - (days_to_keep * 24 * 60 * 60)
delete_count = 0

for filename in os.listdir(report_dir):
filepath = os.path.join(report_dir, filename)
if os.path.isfile(filepath):
file_mtime = os.path.getmtime(filepath)
if file_mtime < cutoff:
try:
os.remove(filepath)
delete_count += 1
except Exception as e:
current_app.logger.error(f"Error removing old report: {e}")
current_app.logger.debug(f"Deleted {delete_count} stale reports from {report_dir}")


def qnr_document_id(
subject_id, questionnaire_bank_id, questionnaire_name, iteration,
status):
Expand Down
15 changes: 13 additions & 2 deletions portal/static/js/src/components/ExportInstruments.vue
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@
if (!resultUrl) return false;
var o = {
...this.getDefaultExportObj(),
url: resultUrl
url: resultUrl,
};
localStorage.setItem(this.getCacheExportedDataInfoKey(), JSON.stringify(o));
this.setExportHistory(o);
Expand All @@ -378,7 +378,18 @@
console.log("Unable to parse cached data export info ", e);
resultJSON = null;
}
return resultJSON;
const timestamp = resultJSON.date ? new Date(resultJSON.date) : null;
if (timestamp && !isNaN(timestamp)) { // guard against Invalid Date
const fiveDaysInMs = 5 * 24 * 60 * 60 * 1000;
const isFiveDaysOld = (Date.now() - timestamp) >= fiveDaysInMs;
if (isFiveDaysOld) {
return null;
}
return resultJSON;
} else {
return resultJSON;
}
return null;
},
getExportHistory: function() {
if (this.exportHistory) return this.exportHistory;
Expand Down
4 changes: 3 additions & 1 deletion portal/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,8 +425,10 @@ def update_tous_task(**kwargs):
@celery.task(queue=LOW_PRIORITY)
@scheduled_task
def token_watchdog(**kwargs):
"""Clean up stale tokens and alert service sponsors if nearly expired"""
"""Clean up stale reports and tokens. alert service sponsors if nearly expired"""
from .models.auth import token_janitor
from .models.questionnaire_response import report_dir_janitor
report_dir_janitor()
error_emails = token_janitor()
if error_emails:
return '\nUnable to reach recipient(s): {}'.format(
Expand Down
Loading