changeset 5414:d9386a3924db

vcs: invalidate repo caches _after_ a push finishes Caches were invalidated right after creating the result iterator, before actually applying the change. Caches would thus be refreshed too early and soon be outdated. This bug was especially seen causing errors with missing revisions when creating PRs right after pushing.
author Mads Kiilerich <madski@unity3d.com>
date Thu, 20 Aug 2015 17:29:55 +0200
parents 22a3fa3c4254
children 061ce7c3071a
files kallithea/lib/base.py kallithea/lib/middleware/simplegit.py kallithea/lib/middleware/simplehg.py
diffstat 3 files changed, 29 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/kallithea/lib/base.py	Thu Aug 20 03:26:18 2015 +0200
+++ b/kallithea/lib/base.py	Thu Aug 20 17:29:55 2015 +0200
@@ -520,3 +520,20 @@
             log.error(traceback.format_exc())
             h.flash(safe_str(e), category='error')
             raise webob.exc.HTTPBadRequest()
+
+
+class WSGIResultCloseCallback(object):
+    """Wrap a WSGI result and let close call close after calling the
+    close method on the result.
+    """
+    def __init__(self, result, close):
+        self._result = result
+        self._close = close
+
+    def __iter__(self):
+        return iter(self._result)
+
+    def close(self):
+        if hasattr(self._result, 'close'):
+            self._result.close()
+        self._close()
--- a/kallithea/lib/middleware/simplegit.py	Thu Aug 20 03:26:18 2015 +0200
+++ b/kallithea/lib/middleware/simplegit.py	Thu Aug 20 17:29:55 2015 +0200
@@ -40,7 +40,7 @@
 
 from kallithea.lib.utils2 import safe_str, fix_PATH, get_server_url,\
     _set_extras
-from kallithea.lib.base import BaseVCSController
+from kallithea.lib.base import BaseVCSController, WSGIResultCloseCallback
 from kallithea.lib.utils import make_ui, is_valid_repo
 from kallithea.lib.exceptions import HTTPLockedRC
 from kallithea.lib.hooks import pre_pull
@@ -203,7 +203,11 @@
             log.info('%s action on Git repo "%s" by "%s" from %s',
                      action, str_repo_name, safe_str(username), ip_addr)
             app = self.__make_app(repo_name, repo_path, extras)
-            return app(environ, start_response)
+            result = app(environ, start_response)
+            if action == 'push':
+                result = WSGIResultCloseCallback(result,
+                    lambda: self._invalidate_cache(repo_name))
+            return result
         except HTTPLockedRC as e:
             _code = CONFIG.get('lock_ret_code')
             log.debug('Repository LOCKED ret code %s!', _code)
@@ -211,10 +215,6 @@
         except Exception:
             log.error(traceback.format_exc())
             return HTTPInternalServerError()(environ, start_response)
-        finally:
-            # invalidate cache on push
-            if action == 'push':
-                self._invalidate_cache(repo_name)
 
     def __make_app(self, repo_name, repo_path, extras):
         """
--- a/kallithea/lib/middleware/simplehg.py	Thu Aug 20 03:26:18 2015 +0200
+++ b/kallithea/lib/middleware/simplehg.py	Thu Aug 20 17:29:55 2015 +0200
@@ -39,7 +39,7 @@
 
 from kallithea.lib.utils2 import safe_str, fix_PATH, get_server_url,\
     _set_extras
-from kallithea.lib.base import BaseVCSController
+from kallithea.lib.base import BaseVCSController, WSGIResultCloseCallback
 from kallithea.lib.utils import make_ui, is_valid_repo, ui_sections
 from kallithea.lib.vcs.utils.hgcompat import RepoError, hgweb_mod
 from kallithea.lib.exceptions import HTTPLockedRC
@@ -205,7 +205,11 @@
             log.info('%s action on Mercurial repo "%s" by "%s" from %s',
                      action, str_repo_name, safe_str(username), ip_addr)
             app = self.__make_app(repo_path, baseui, extras)
-            return app(environ, start_response)
+            result = app(environ, start_response)
+            if action == 'push':
+                result = WSGIResultCloseCallback(result,
+                    lambda: self._invalidate_cache(repo_name))
+            return result
         except RepoError as e:
             if str(e).find('not found') != -1:
                 return HTTPNotFound()(environ, start_response)
@@ -216,10 +220,6 @@
         except Exception:
             log.error(traceback.format_exc())
             return HTTPInternalServerError()(environ, start_response)
-        finally:
-            # invalidate cache on push
-            if action == 'push':
-                self._invalidate_cache(repo_name)
 
     def __make_app(self, repo_name, baseui, extras):
         """