From 6c5eec79819014863aa69bb06b756008eb8ba89d Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Wed, 19 Aug 2015 18:49:09 -0500 Subject: [PATCH] Add progress indicator to batch execution. Also disable Execute button immediately when clicked. --- tailbone/templates/batch/view.mako | 24 ++++++++++++ tailbone/views/batch.py | 61 +++++++++++++++++++++++++++--- 2 files changed, 80 insertions(+), 5 deletions(-) diff --git a/tailbone/templates/batch/view.mako b/tailbone/templates/batch/view.mako index d6922b7c..dd8ae649 100644 --- a/tailbone/templates/batch/view.mako +++ b/tailbone/templates/batch/view.mako @@ -1,3 +1,27 @@ ## -*- coding: utf-8 -*- <%inherit file="/batch/crud.mako" /> + +<%def name="head_tags()"> + ${parent.head_tags()} + + + +<%def name="buttons()"> +
+ % if not form.readonly and batch.refreshable: + ${h.submit('save-refresh', "Save & Refresh Data")} + % endif + % if not batch.executed and request.has_perm('{0}.execute'.format(permission_prefix)): + + % endif +
+ + ${parent.body()} diff --git a/tailbone/views/batch.py b/tailbone/views/batch.py index 3224654d..b824bece 100644 --- a/tailbone/views/batch.py +++ b/tailbone/views/batch.py @@ -647,13 +647,64 @@ class BatchCrud(BaseCrud): return self.request.route_url('{0}.refresh'.format(self.route_prefix), uuid=uuid) def execute(self): + """ + Execute a batch. Starts a separate thread for the execution, and + displays a progress indicator page. + """ batch = self.current_batch() - if self.handler.execute(batch): - batch.executed = datetime.datetime.utcnow() - batch.executed_by = self.request.user - self.request.session.flash("Batch was executed successfully.") - return HTTPFound(location=self.view_url(batch.uuid)) + key = '{0}.execute'.format(self.batch_class.__tablename__) + progress = SessionProgress(self.request, key) + thread = Thread(target=self.execute_thread, args=(batch.uuid, progress)) + thread.start() + + kwargs = { + 'key': key, + 'cancel_url': self.view_url(batch.uuid), + 'cancel_msg': "Batch execution was canceled.", + } + return render_to_response('/progress.mako', kwargs, request=self.request) + + def execute_thread(self, batch_uuid, progress=None): + """ + Thread target for executing a batch with progress indicator. + """ + # Execute the batch, with progress. Note that we must use the rattail + # session here; can't use tailbone because it has web request + # transaction binding etc. + session = RatSession() + batch = session.query(self.batch_class).get(batch_uuid) + try: + result = self.handler.execute(batch, progress=progress) + + # If anything goes wrong, rollback and log the error etc. + except Exception as error: + session.rollback() + log.exception("execution failed for batch: {0}".format(batch)) + session.close() + if progress: + progress.session.load() + progress.session['error'] = True + progress.session['error_msg'] = "Batch execution failed: {0}".format(error) + progress.session.save() + + # If no error, check result flag (false means user canceled). + else: + if result: + batch.executed = datetime.datetime.utcnow() + batch.executed_by = self.request.user + session.commit() + else: + session.rollback() + session.refresh(batch) + session.close() + + if progress: + progress.session.load() + progress.session['complete'] = True + progress.session['success_url'] = self.view_url(batch.uuid) + progress.session.save() + class FileBatchCrud(BatchCrud): """