[#5705] Moved refreshing of tracker bin counts to task to prevent blocking requests
Signed-off-by: Cory Johns <johnsca@geek.net>
diff --git a/ForgeTracker/forgetracker/import_support.py b/ForgeTracker/forgetracker/import_support.py
index ff58452..4e587fb 100644
--- a/ForgeTracker/forgetracker/import_support.py
+++ b/ForgeTracker/forgetracker/import_support.py
@@ -250,7 +250,7 @@
return {'status': True, 'errors': self.errors, 'warnings': self.warnings}
def perform_import(self, doc, options, **post_data):
- log.info('import called: %s', options)
+ log.info('import called: %s', options)
self.init_options(options)
self.validate_user_mapping()
@@ -263,12 +263,12 @@
log.info('Import id: %s', c.api_token.api_key)
artifacts = project_doc['trackers'][tracker_names[0]]['artifacts']
-
+
if self.option('create_users'):
users = self.collect_users(artifacts)
unknown_users = self.find_unknown_users(users)
self.make_user_placeholders(unknown_users)
-
+
M.session.artifact_orm_session._get().skip_mod_date = True
for a in artifacts:
comments = a.pop('comments', [])
@@ -283,5 +283,6 @@
except Exception, e:
self.warnings.append('Could not import attachment, skipped: %s' % e)
log.info('Imported ticket: %d', t.ticket_num)
+ c.app.globals.invalidate_bin_counts()
return {'status': True, 'errors': self.errors, 'warnings': self.warnings}
diff --git a/ForgeTracker/forgetracker/model/ticket.py b/ForgeTracker/forgetracker/model/ticket.py
index 15241c6..18d0fe2 100644
--- a/ForgeTracker/forgetracker/model/ticket.py
+++ b/ForgeTracker/forgetracker/model/ticket.py
@@ -54,8 +54,7 @@
_bin_counts = FieldProperty(schema.Deprecated) # {str:int})
_bin_counts_data = FieldProperty([dict(summary=str, hits=int)])
_bin_counts_expire = FieldProperty(datetime)
- _milestone_counts = FieldProperty([dict(name=str,hits=int,closed=int)])
- _milestone_counts_expire = FieldProperty(datetime)
+ _bin_counts_invalidated = FieldProperty(datetime)
show_in_search = FieldProperty({str: bool}, if_missing={'ticket_num': True,
'summary': True,
'_milestone': True,
@@ -115,7 +114,7 @@
return fld
return None
- def _refresh_counts(self):
+ def update_bin_counts(self):
# Refresh bin counts
self._bin_counts_data = []
for b in Bin.query.find(dict(
@@ -125,10 +124,11 @@
self._bin_counts_data.append(dict(summary=b.summary, hits=hits))
self._bin_counts_expire = \
datetime.utcnow() + timedelta(minutes=60)
+ self._bin_counts_invalidated = None
def bin_count(self, name):
if self._bin_counts_expire < datetime.utcnow():
- self._refresh_counts()
+ self.invalidate_bin_counts()
for d in self._bin_counts_data:
if d['summary'] == name: return d
return dict(summary=name, hits=0)
@@ -148,10 +148,14 @@
return d
def invalidate_bin_counts(self):
- '''Expire it just a bit in the future to allow data to propagate through
- the search task
- '''
- self._bin_counts_expire = datetime.utcnow() + timedelta(seconds=5)
+ '''Force expiry of bin counts and queue them to be updated.'''
+ invalidation_expiry = datetime.utcnow() - timedelta(minutes=5)
+ if self._bin_counts_invalidated is not None and \
+ self._bin_counts_invalidated > invalidation_expiry:
+ return
+ self._bin_counts_invalidated = datetime.utcnow()
+ from forgetracker import tasks # prevent circular import
+ tasks.update_bin_counts.post(self.app_config_id)
def sortable_custom_fields_shown_in_search(self):
return [dict(sortable_name='%s_s' % field['name'],
@@ -481,7 +485,6 @@
app_config_id=self.app_config_id, artifact_id=self._id, type='attachment'))
def update(self, ticket_form):
- self.globals.invalidate_bin_counts()
# update is not allowed to change the ticket_num
ticket_form.pop('ticket_num', None)
self.labels = ticket_form.pop('labels', [])
@@ -570,7 +573,6 @@
custom_fields[fn] = old_val
self.custom_fields = custom_fields
- self.globals.invalidate_bin_counts()
# move ticket. ensure unique ticket_num
while True:
with h.push_context(app_config.project_id, app_config_id=app_config._id):
diff --git a/ForgeTracker/forgetracker/tasks.py b/ForgeTracker/forgetracker/tasks.py
new file mode 100644
index 0000000..3e88aae
--- /dev/null
+++ b/ForgeTracker/forgetracker/tasks.py
@@ -0,0 +1,17 @@
+import logging
+
+from pylons import c
+from allura.lib.decorators import task
+from allura.lib import helpers as h
+
+from allura import model as M
+
+log = logging.getLogger(__name__)
+
+
+@task
+def update_bin_counts(app_config_id):
+ app_config = M.AppConfig.query.get(_id=app_config_id)
+ app = app_config.project.app_instance(app_config)
+ with h.push_config(c, app=app):
+ app.globals.update_bin_counts()
diff --git a/ForgeTracker/forgetracker/tracker_main.py b/ForgeTracker/forgetracker/tracker_main.py
index 2312388..8b9362c 100644
--- a/ForgeTracker/forgetracker/tracker_main.py
+++ b/ForgeTracker/forgetracker/tracker_main.py
@@ -314,7 +314,7 @@
milestones=[
dict(name='1.0', complete=False, due_date=None),
dict(name='2.0', complete=False, due_date=None)]) ])
- c.app.globals.invalidate_bin_counts()
+ self.globals.update_bin_counts()
# create default search bins
TM.Bin(summary='Open Tickets', terms=self.globals.not_closed_query,
app_config_id = self.config._id, custom_fields = dict())
@@ -681,6 +681,7 @@
require_access(c.app, 'create')
ticket = TM.Ticket.new()
ticket.update(ticket_form)
+ c.app.globals.invalidate_bin_counts()
g.director.create_activity(c.user, 'created', ticket,
related_nodes=[c.project])
redirect(str(ticket.ticket_num)+'/')
@@ -1021,8 +1022,8 @@
# page so the user can fix the errors.
return dict(bins=saved_bins, count=len(bins), app=self.app,
new_bin=new_bin, errors=errors)
- # No errors, redirect to search bin list page.
self.app.globals.invalidate_bin_counts()
+ # No errors, redirect to search bin list page.
redirect('.')
class changelog(object):
@@ -1325,6 +1326,7 @@
redirect(request.referer)
new_ticket = self.ticket.move(tracker)
+ c.app.globals.invalidate_bin_counts()
flash('Ticket successfully moved')
redirect(new_ticket.url())