Refactor progress bars somewhat to allow file-based sessions

hoping this solves issue of Apache restart at end of upgrade
This commit is contained in:
Lance Edgar 2017-08-07 18:19:29 -05:00
parent f203f2c377
commit f46e20c119
8 changed files with 48 additions and 37 deletions

View file

@ -1,4 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8; -*-
################################################################################ ################################################################################
# #
# Rattail -- Retail Software Framework # Rattail -- Retail Software Framework
@ -26,15 +26,21 @@ Progress Indicator
from __future__ import unicode_literals, absolute_import from __future__ import unicode_literals, absolute_import
import os
from beaker.session import Session 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. Create/get a Beaker session object, to be used for progress.
""" """
id = '{0}.progress.{1}'.format(request.session.id, key) id = '{}.progress.{}'.format(request.session.id, key)
return Session(request, id, use_cookies=False) 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): class SessionProgress(object):
@ -46,8 +52,9 @@ class SessionProgress(object):
for display to the user. for display to the user.
""" """
def __init__(self, request, key): def __init__(self, request, key, session_type=None):
self.session = get_progress_session(request, key) self.key = key
self.session = get_progress_session(request, key, type=session_type)
self.canceled = False self.canceled = False
self.clear() self.clear()

View file

@ -1,4 +1,4 @@
## -*- coding: utf-8 -*- ## -*- coding: utf-8; -*-
<%namespace file="tailbone:templates/base.mako" import="core_javascript" /> <%namespace file="tailbone:templates/base.mako" import="core_javascript" />
<%namespace file="/base.mako" import="jquery_theme" /> <%namespace file="/base.mako" import="jquery_theme" />
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
@ -64,7 +64,7 @@
function update_progress() { function update_progress() {
$.ajax({ $.ajax({
url: '${url('progress', key=key)}', url: '${url('progress', key=progress.key)}?sessiontype=${progress.session.type}',
success: function(data) { success: function(data) {
if (data.error) { if (data.error) {
location.href = '${cancel_url}'; location.href = '${cancel_url}';
@ -106,7 +106,7 @@
clearInterval(updater); clearInterval(updater);
$(this).button('disable').button('option', 'label', "Canceling, please wait..."); $(this).button('disable').button('option', 'label', "Canceling, please wait...");
$.ajax({ $.ajax({
url: '${url('progress.cancel', key=key)}', url: '${url('progress', key=progress.key)}?sessiontype=${progress.session.type}',
data: { data: {
'cancel_msg': '${cancel_msg}', 'cancel_msg': '${cancel_msg}',
}, },

View file

@ -506,14 +506,13 @@ class BatchMasterView(MasterView):
permission_prefix = self.get_permission_prefix() permission_prefix = self.get_permission_prefix()
# showing progress requires a separate thread; start that first # showing progress requires a separate thread; start that first
progress_key = '{}.prefill'.format(route_prefix) key = '{}.prefill'.format(route_prefix)
progress = SessionProgress(self.request, progress_key) progress = SessionProgress(self.request, key)
thread = Thread(target=self.prefill_thread, args=(batch.uuid, progress)) thread = Thread(target=self.prefill_thread, args=(batch.uuid, progress))
thread.start() thread.start()
# Send user to progress page. # Send user to progress page.
kwargs = { kwargs = {
'key': progress_key,
'cancel_url': self.get_action_url('view', batch), 'cancel_url': self.get_action_url('view', batch),
'cancel_msg': "Batch prefill was canceled.", 'cancel_msg': "Batch prefill was canceled.",
} }
@ -522,7 +521,7 @@ class BatchMasterView(MasterView):
if not self.request.has_perm('{}.view'.format(permission_prefix)): if not self.request.has_perm('{}.view'.format(permission_prefix)):
kwargs['cancel_url'] = self.request.route_url('{}.create'.format(route_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): def prefill_thread(self, batch_uuid, progress):
""" """
@ -601,16 +600,15 @@ class BatchMasterView(MasterView):
# Send user to progress page. # Send user to progress page.
kwargs = { kwargs = {
'key': key,
'cancel_url': self.get_action_url('view', batch), 'cancel_url': self.get_action_url('view', batch),
'cancel_msg': "Batch refresh was canceled.", 'cancel_msg': "Batch refresh was canceled.",
} }
# TODO: This seems hacky...it exists for (only) one specific scenario. # TODO: This seems hacky...it exists for (only) one specific scenario.
if not self.request.has_perm('{}.view'.format(permission_prefix)): if not self.request.has_perm('{}.view'.format(permission_prefix)):
kwargs['cancel_url'] = self.request.route_url('{}.create'.format(route_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): 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) self.request.session['batch.{}.execute_option.{}'.format(batch.batch_key, key)] = unicode(value)
key = '{}.execute'.format(self.model_class.__tablename__) 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 = Thread(target=self.execute_thread, args=(batch.uuid, self.request.user.uuid), kwargs=kwargs)
thread.start() thread.start()
return self.render_progress({ return self.render_progress(progress, {
'key': key,
'cancel_url': self.get_action_url('view', batch), 'cancel_url': self.get_action_url('view', batch),
'cancel_msg': "Batch execution was canceled.", 'cancel_msg': "Batch execution was canceled.",
}) })
@ -850,12 +848,12 @@ class BatchMasterView(MasterView):
key = '{}.execute_results'.format(self.model_class.__tablename__) key = '{}.execute_results'.format(self.model_class.__tablename__)
batches = self.get_effective_data() 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 = Thread(target=self.execute_results_thread, args=(batches, self.request.user.uuid), kwargs=kwargs)
thread.start() thread.start()
return self.render_progress({ return self.render_progress(progress, {
'key': key,
'cancel_url': self.get_index_url(), 'cancel_url': self.get_index_url(),
'cancel_msg': "Batch execution was canceled", 'cancel_msg': "Batch execution was canceled",
}) })

View file

@ -90,10 +90,11 @@ class View(object):
def progress_loop(self, func, items, factory, *args, **kwargs): def progress_loop(self, func, items, factory, *args, **kwargs):
return progress_loop(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. Render the progress page, with given kwargs as context.
""" """
kwargs['progress'] = progress
return render_to_response('/progress.mako', kwargs, request=self.request) return render_to_response('/progress.mako', kwargs, request=self.request)
def file_response(self, path): def file_response(self, path):

View file

@ -741,13 +741,12 @@ class MasterView(View):
Delete all records matching the current grid query Delete all records matching the current grid query
""" """
if self.request.method == 'POST': if self.request.method == 'POST':
key = '{}.bulk_delete'.format(self.model_class.__tablename__)
objects = self.get_effective_data() objects = self.get_effective_data()
key = '{}.bulk_delete'.format(self.model_class.__tablename__)
progress = SessionProgress(self.request, key) progress = SessionProgress(self.request, key)
thread = Thread(target=self.bulk_delete_thread, args=(objects, progress)) thread = Thread(target=self.bulk_delete_thread, args=(objects, progress))
thread.start() thread.start()
return self.render_progress({ return self.render_progress(progress, {
'key': key,
'cancel_url': self.get_index_url(), 'cancel_url': self.get_index_url(),
'cancel_msg': "Bulk deletion was canceled", 'cancel_msg': "Bulk deletion was canceled",
}) })
@ -804,13 +803,12 @@ class MasterView(View):
model_title = self.get_model_title() model_title = self.get_model_title()
if self.request.method == 'POST': if self.request.method == 'POST':
key = '{}.execute'.format(self.get_grid_key()) progress = self.make_execute_progress()
kwargs = {'progress': SessionProgress(self.request, key)} kwargs = {'progress': progress}
thread = Thread(target=self.execute_thread, args=(obj.uuid, self.request.user.uuid), kwargs=kwargs) thread = Thread(target=self.execute_thread, args=(obj.uuid, self.request.user.uuid), kwargs=kwargs)
thread.start() thread.start()
return self.render_progress({ return self.render_progress(progress, {
'key': key,
'cancel_url': self.get_action_url('view', obj), 'cancel_url': self.get_action_url('view', obj),
'cancel_msg': "{} execution was canceled".format(model_title), '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') self.request.session.flash("Sorry, you must POST to execute a {}.".format(model_title), 'error')
return self.redirect(self.get_action_url('view', obj)) 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): def execute_thread(self, uuid, user_uuid, progress=None, **kwargs):
""" """
Thread target for executing an object. Thread target for executing an object.

View file

@ -489,13 +489,11 @@ class ProductsView(MasterView):
handler = get_batch_handler(self.rattail_config, batch_key, handler = get_batch_handler(self.rattail_config, batch_key,
default=supported[batch_key].spec) default=supported[batch_key].spec)
products = self.get_effective_data() products = self.get_effective_data()
progress_key = 'products.batch' progress = SessionProgress(self.request, 'products.batch')
progress = SessionProgress(self.request, progress_key)
thread = Thread(target=self.make_batch_thread, thread = Thread(target=self.make_batch_thread,
args=(handler, self.request.user.uuid, products, params, progress)) args=(handler, self.request.user.uuid, products, params, progress))
thread.start() thread.start()
return self.render_progress({ return self.render_progress(progress, {
'key': progress_key,
'cancel_url': self.get_index_url(), 'cancel_url': self.get_index_url(),
'cancel_msg': "Batch creation was canceled.", 'cancel_msg': "Batch creation was canceled.",
}) })

View file

@ -20,17 +20,18 @@
# Rattail. If not, see <http://www.gnu.org/licenses/>. # Rattail. If not, see <http://www.gnu.org/licenses/>.
# #
################################################################################ ################################################################################
""" """
Progress Views 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): def progress(request):
key = request.matchdict['key'] 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'): if session.get('complete'):
msg = session.get('success_msg') msg = session.get('success_msg')
if msg: if msg:

View file

@ -183,6 +183,10 @@ class UpgradeView(MasterView):
def before_create_flush(self, upgrade): def before_create_flush(self, upgrade):
upgrade.created_by = self.request.user 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): def execute_instance(self, upgrade, user, **kwargs):
session = orm.object_session(upgrade) session = orm.object_session(upgrade)
upgrade.executing = True upgrade.executing = True