From f46e20c119e270b8ee029470ae5fbaccf5a185a9 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 7 Aug 2017 18:19:29 -0500 Subject: [PATCH] Refactor progress bars somewhat to allow file-based sessions hoping this solves issue of Apache restart at end of upgrade --- tailbone/progress.py | 19 +++++++++++++------ tailbone/templates/progress.mako | 6 +++--- tailbone/views/batch/core.py | 24 +++++++++++------------- tailbone/views/core.py | 3 ++- tailbone/views/master.py | 16 +++++++++------- tailbone/views/products.py | 6 ++---- tailbone/views/progress.py | 7 ++++--- tailbone/views/upgrades.py | 4 ++++ 8 files changed, 48 insertions(+), 37 deletions(-) diff --git a/tailbone/progress.py b/tailbone/progress.py index e6d35b9a..0879025b 100644 --- a/tailbone/progress.py +++ b/tailbone/progress.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# -*- coding: utf-8; -*- ################################################################################ # # Rattail -- Retail Software Framework @@ -26,15 +26,21 @@ Progress Indicator from __future__ import unicode_literals, absolute_import +import os + from beaker.session import Session -def get_progress_session(request, key): +def get_progress_session(request, key, **kwargs): """ Create/get a Beaker session object, to be used for progress. """ - id = '{0}.progress.{1}'.format(request.session.id, key) - return Session(request, id, use_cookies=False) + id = '{}.progress.{}'.format(request.session.id, key) + kwargs['use_cookies'] = False + if kwargs.get('type') == 'file': + kwargs['data_dir'] = os.path.join(request.rattail_config.appdir(), 'sessions') + session = Session(request, id, **kwargs) + return session class SessionProgress(object): @@ -46,8 +52,9 @@ class SessionProgress(object): for display to the user. """ - def __init__(self, request, key): - self.session = get_progress_session(request, key) + def __init__(self, request, key, session_type=None): + self.key = key + self.session = get_progress_session(request, key, type=session_type) self.canceled = False self.clear() diff --git a/tailbone/templates/progress.mako b/tailbone/templates/progress.mako index bab70473..4bd2b4bd 100644 --- a/tailbone/templates/progress.mako +++ b/tailbone/templates/progress.mako @@ -1,4 +1,4 @@ -## -*- coding: utf-8 -*- +## -*- coding: utf-8; -*- <%namespace file="tailbone:templates/base.mako" import="core_javascript" /> <%namespace file="/base.mako" import="jquery_theme" /> @@ -64,7 +64,7 @@ function update_progress() { $.ajax({ - url: '${url('progress', key=key)}', + url: '${url('progress', key=progress.key)}?sessiontype=${progress.session.type}', success: function(data) { if (data.error) { location.href = '${cancel_url}'; @@ -106,7 +106,7 @@ clearInterval(updater); $(this).button('disable').button('option', 'label', "Canceling, please wait..."); $.ajax({ - url: '${url('progress.cancel', key=key)}', + url: '${url('progress', key=progress.key)}?sessiontype=${progress.session.type}', data: { 'cancel_msg': '${cancel_msg}', }, diff --git a/tailbone/views/batch/core.py b/tailbone/views/batch/core.py index 6c4f005e..a3a9891d 100644 --- a/tailbone/views/batch/core.py +++ b/tailbone/views/batch/core.py @@ -506,14 +506,13 @@ class BatchMasterView(MasterView): permission_prefix = self.get_permission_prefix() # showing progress requires a separate thread; start that first - progress_key = '{}.prefill'.format(route_prefix) - progress = SessionProgress(self.request, progress_key) + key = '{}.prefill'.format(route_prefix) + progress = SessionProgress(self.request, key) thread = Thread(target=self.prefill_thread, args=(batch.uuid, progress)) thread.start() # Send user to progress page. kwargs = { - 'key': progress_key, 'cancel_url': self.get_action_url('view', batch), 'cancel_msg': "Batch prefill was canceled.", } @@ -522,7 +521,7 @@ class BatchMasterView(MasterView): if not self.request.has_perm('{}.view'.format(permission_prefix)): kwargs['cancel_url'] = self.request.route_url('{}.create'.format(route_prefix)) - return self.render_progress(kwargs) + return self.render_progress(progress, kwargs) def prefill_thread(self, batch_uuid, progress): """ @@ -601,16 +600,15 @@ class BatchMasterView(MasterView): # Send user to progress page. kwargs = { - 'key': key, 'cancel_url': self.get_action_url('view', batch), 'cancel_msg': "Batch refresh was canceled.", - } + } # TODO: This seems hacky...it exists for (only) one specific scenario. if not self.request.has_perm('{}.view'.format(permission_prefix)): kwargs['cancel_url'] = self.request.route_url('{}.create'.format(route_prefix)) - return self.render_progress(kwargs) + return self.render_progress(progress, kwargs) def refresh_data(self, session, batch, cognizer=None, progress=None): """ @@ -764,12 +762,12 @@ class BatchMasterView(MasterView): self.request.session['batch.{}.execute_option.{}'.format(batch.batch_key, key)] = unicode(value) key = '{}.execute'.format(self.model_class.__tablename__) - kwargs['progress'] = SessionProgress(self.request, key) + progress = SessionProgress(self.request, key) + kwargs['progress'] = progress thread = Thread(target=self.execute_thread, args=(batch.uuid, self.request.user.uuid), kwargs=kwargs) thread.start() - return self.render_progress({ - 'key': key, + return self.render_progress(progress, { 'cancel_url': self.get_action_url('view', batch), 'cancel_msg': "Batch execution was canceled.", }) @@ -850,12 +848,12 @@ class BatchMasterView(MasterView): key = '{}.execute_results'.format(self.model_class.__tablename__) batches = self.get_effective_data() - kwargs['progress'] = SessionProgress(self.request, key) + progress = SessionProgress(self.request, key) + kwargs['progress'] = progress thread = Thread(target=self.execute_results_thread, args=(batches, self.request.user.uuid), kwargs=kwargs) thread.start() - return self.render_progress({ - 'key': key, + return self.render_progress(progress, { 'cancel_url': self.get_index_url(), 'cancel_msg': "Batch execution was canceled", }) diff --git a/tailbone/views/core.py b/tailbone/views/core.py index 9efdb90f..c1a2f0fe 100644 --- a/tailbone/views/core.py +++ b/tailbone/views/core.py @@ -90,10 +90,11 @@ class View(object): def progress_loop(self, func, items, factory, *args, **kwargs): return progress_loop(func, items, factory, *args, **kwargs) - def render_progress(self, kwargs): + def render_progress(self, progress, kwargs): """ Render the progress page, with given kwargs as context. """ + kwargs['progress'] = progress return render_to_response('/progress.mako', kwargs, request=self.request) def file_response(self, path): diff --git a/tailbone/views/master.py b/tailbone/views/master.py index e4e32beb..f772f365 100644 --- a/tailbone/views/master.py +++ b/tailbone/views/master.py @@ -741,13 +741,12 @@ class MasterView(View): Delete all records matching the current grid query """ if self.request.method == 'POST': - key = '{}.bulk_delete'.format(self.model_class.__tablename__) objects = self.get_effective_data() + key = '{}.bulk_delete'.format(self.model_class.__tablename__) progress = SessionProgress(self.request, key) thread = Thread(target=self.bulk_delete_thread, args=(objects, progress)) thread.start() - return self.render_progress({ - 'key': key, + return self.render_progress(progress, { 'cancel_url': self.get_index_url(), 'cancel_msg': "Bulk deletion was canceled", }) @@ -804,13 +803,12 @@ class MasterView(View): model_title = self.get_model_title() if self.request.method == 'POST': - key = '{}.execute'.format(self.get_grid_key()) - kwargs = {'progress': SessionProgress(self.request, key)} + progress = self.make_execute_progress() + kwargs = {'progress': progress} thread = Thread(target=self.execute_thread, args=(obj.uuid, self.request.user.uuid), kwargs=kwargs) thread.start() - return self.render_progress({ - 'key': key, + return self.render_progress(progress, { 'cancel_url': self.get_action_url('view', obj), 'cancel_msg': "{} execution was canceled".format(model_title), }) @@ -818,6 +816,10 @@ class MasterView(View): self.request.session.flash("Sorry, you must POST to execute a {}.".format(model_title), 'error') return self.redirect(self.get_action_url('view', obj)) + def make_execute_progress(self): + key = '{}.execute'.format(self.get_grid_key()) + return SessionProgress(self.request, key) + def execute_thread(self, uuid, user_uuid, progress=None, **kwargs): """ Thread target for executing an object. diff --git a/tailbone/views/products.py b/tailbone/views/products.py index bf4fcd92..10f85361 100644 --- a/tailbone/views/products.py +++ b/tailbone/views/products.py @@ -489,13 +489,11 @@ class ProductsView(MasterView): handler = get_batch_handler(self.rattail_config, batch_key, default=supported[batch_key].spec) products = self.get_effective_data() - progress_key = 'products.batch' - progress = SessionProgress(self.request, progress_key) + progress = SessionProgress(self.request, 'products.batch') thread = Thread(target=self.make_batch_thread, args=(handler, self.request.user.uuid, products, params, progress)) thread.start() - return self.render_progress({ - 'key': progress_key, + return self.render_progress(progress, { 'cancel_url': self.get_index_url(), 'cancel_msg': "Batch creation was canceled.", }) diff --git a/tailbone/views/progress.py b/tailbone/views/progress.py index b6c583f1..e3cbef01 100644 --- a/tailbone/views/progress.py +++ b/tailbone/views/progress.py @@ -20,17 +20,18 @@ # Rattail. If not, see . # ################################################################################ - """ Progress Views """ -from ..progress import get_progress_session +from __future__ import unicode_literals, absolute_import + +from tailbone.progress import get_progress_session def progress(request): key = request.matchdict['key'] - session = get_progress_session(request, key) + session = get_progress_session(request, key, type=request.GET.get('sessiontype')) if session.get('complete'): msg = session.get('success_msg') if msg: diff --git a/tailbone/views/upgrades.py b/tailbone/views/upgrades.py index d83b382c..380e0723 100644 --- a/tailbone/views/upgrades.py +++ b/tailbone/views/upgrades.py @@ -183,6 +183,10 @@ class UpgradeView(MasterView): def before_create_flush(self, upgrade): upgrade.created_by = self.request.user + def make_execute_progress(self): + key = '{}.execute'.format(self.get_grid_key()) + return SessionProgress(self.request, key, session_type='file') + def execute_instance(self, upgrade, user, **kwargs): session = orm.object_session(upgrade) upgrade.executing = True