From c5e8f6700555ff3a3efd4488b9fa4714dbd771c5 Mon Sep 17 00:00:00 2001 From: Adrian Moennich Date: Wed, 22 Jul 2015 18:26:33 +0200 Subject: [PATCH] Delete attachment packages after 1h --- indico/core/celery/__init__.py | 1 + .../attachments/controllers/event_package.py | 8 +++- indico/util/tasks.py | 47 ++++++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 indico/util/tasks.py diff --git a/indico/core/celery/__init__.py b/indico/core/celery/__init__.py index 5a92bb5fa..e9b47c19a 100644 --- a/indico/core/celery/__init__.py +++ b/indico/core/celery/__init__.py @@ -37,6 +37,7 @@ def _load_default_modules(app, **kwargs): @import_modules.connect def _import_modules(*args, **kwargs): + import indico.util.tasks signals.import_tasks.send() diff --git a/indico/modules/attachments/controllers/event_package.py b/indico/modules/attachments/controllers/event_package.py index d19942237..defd7f6ce 100644 --- a/indico/modules/attachments/controllers/event_package.py +++ b/indico/modules/attachments/controllers/event_package.py @@ -29,6 +29,7 @@ from indico.core.db.sqlalchemy.links import LinkType from indico.util.fs import secure_filename from indico.util.date_time import format_date from indico.util.string import to_unicode +from indico.util.tasks import delete_file from indico.web.flask.util import send_file from indico.modules.attachments.forms import AttachmentPackageForm from indico.modules.attachments.models.attachments import Attachment, AttachmentFile, AttachmentType @@ -101,7 +102,7 @@ class AttachmentPackageGeneratorMixin: def _generate_zip_file(self, attachments): # XXX: could use a celery task to delay the temporary file after a day or so. # right now this relies on an external cronjob to do so... - temp_file = NamedTemporaryFile(suffix='indico.tmp', dir=Config.getInstance().getTempDir(), delete=False) + temp_file = NamedTemporaryFile(suffix='indico.tmp', dir=Config.getInstance().getTempDir()) with ZipFile(temp_file.name, 'w', allowZip64=True) as zip_handler: self.used = set() for attachment in attachments: @@ -110,6 +111,11 @@ class AttachmentPackageGeneratorMixin: with attachment.file.storage.get_local_path(attachment.file.storage_file_id) as filepath: zip_handler.write(filepath, name) + # Delete the temporary file after some time. Even for a large file we don't + # need a higher delay since the webserver will keep it open anyway until it's + # done sending it to the client. + delete_file.apply_async(args=[temp_file.name], countdown=3600) + temp_file.delete = False return send_file('material-{}.zip'.format(self._conf.id), temp_file.name, 'application/zip', inline=False) def _prepare_folder_structure(self, attachment): diff --git a/indico/util/tasks.py b/indico/util/tasks.py new file mode 100644 index 000000000..c1871cdfb --- /dev/null +++ b/indico/util/tasks.py @@ -0,0 +1,47 @@ +# This file is part of Indico. +# Copyright (C) 2002 - 2015 European Organization for Nuclear Research (CERN). +# +# Indico is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3 of the +# License, or (at your option) any later version. +# +# Indico is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Indico; if not, see . + +""" +This module contains very generic Celery tasks which are not specific +to any other module. Please add tasks in here only if they are generic +enough to be possibly useful somewhere else. If you need to import +anything from `indico.modules`, your task most likely does not belong +in here but in your module instead. +""" + +from __future__ import unicode_literals + +import os + +from indico.core.celery import celery +from indico.core.logger import Logger +from indico.util.fs import silentremove + + +@celery.task(name='delete_file') +def delete_file(path): + """Deletes a file. + + This task is meant to be invoked with a delay, i.e. like this:: + + delete_file.apply_async(args=[file_path], countdown=3600) + + :param path: The absolute path to the file. + """ + if not os.path.isabs(path): + raise ValueError('Path is not absolute: {}'.format(path)) + Logger.get().info('Deleting {}'.format(path)) + silentremove(path) -- 2.11.4.GIT