You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by br...@apache.org on 2013/02/05 22:03:15 UTC

[2/2] git commit: [#5705] Moved refreshing of tracker bin counts to task to prevent blocking requests

Updated Branches:
  refs/heads/master 0fb11fe39 -> bb34f6a3c


[#5705] Moved refreshing of tracker bin counts to task to prevent blocking requests

Signed-off-by: Cory Johns <jo...@geek.net>


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/3c7c8f6d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/3c7c8f6d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/3c7c8f6d

Branch: refs/heads/master
Commit: 3c7c8f6dfcdd3a4e92c7800e750bf9ebd1ddab27
Parents: 0fb11fe
Author: Cory Johns <jo...@geek.net>
Authored: Fri Feb 1 00:27:47 2013 +0000
Committer: Dave Brondsema <db...@geek.net>
Committed: Tue Feb 5 21:01:10 2013 +0000

----------------------------------------------------------------------
 ForgeTracker/forgetracker/import_support.py |    7 ++++---
 ForgeTracker/forgetracker/model/ticket.py   |   22 ++++++++++++----------
 ForgeTracker/forgetracker/tasks.py          |   17 +++++++++++++++++
 ForgeTracker/forgetracker/tracker_main.py   |    6 ++++--
 4 files changed, 37 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/3c7c8f6d/ForgeTracker/forgetracker/import_support.py
----------------------------------------------------------------------
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 @@ option user_map to avoid losing username information. Unknown users: %s''' % unk
         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 @@ option user_map to avoid losing username information. Unknown users: %s''' % unk
         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 @@ option user_map to avoid losing username information. Unknown users: %s''' % unk
                 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}

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/3c7c8f6d/ForgeTracker/forgetracker/model/ticket.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/model/ticket.py b/ForgeTracker/forgetracker/model/ticket.py
index 5beb197..82a52c1 100644
--- a/ForgeTracker/forgetracker/model/ticket.py
+++ b/ForgeTracker/forgetracker/model/ticket.py
@@ -54,8 +54,7 @@ class Globals(MappedClass):
     _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 @@ class Globals(MappedClass):
                 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 @@ class Globals(MappedClass):
             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 @@ class Globals(MappedClass):
         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 @@ class Ticket(VersionedArtifact, ActivityObject, VotableArtifact):
             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', [])
@@ -583,7 +586,6 @@ class Ticket(VersionedArtifact, ActivityObject, VotableArtifact):
             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):

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/3c7c8f6d/ForgeTracker/forgetracker/tasks.py
----------------------------------------------------------------------
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()

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/3c7c8f6d/ForgeTracker/forgetracker/tracker_main.py
----------------------------------------------------------------------
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 @@ class ForgeTrackerApp(Application):
                     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 @@ class RootController(BaseController):
             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 @@ class BinController(BaseController):
             # 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 @@ class TicketController(BaseController):
                 redirect(request.referer)
 
             new_ticket = self.ticket.move(tracker)
+            c.app.globals.invalidate_bin_counts()
             flash('Ticket successfully moved')
             redirect(new_ticket.url())