diff rhodecode/model/scm.py @ 692:cb0d9ce6ac5c beta

#50 on point cache invalidation changes. Created cacheInvalidation table cleaned up sa sessions from models, since it wasn't really needed.
author Marcin Kuzminski <marcin@python-works.com>
date Mon, 15 Nov 2010 02:26:19 +0100
parents 7486da5f0628
children 90ac3255c117
line wrap: on
line diff
--- a/rhodecode/model/scm.py	Sun Nov 14 22:54:16 2010 +0100
+++ b/rhodecode/model/scm.py	Mon Nov 15 02:26:19 2010 +0100
@@ -28,12 +28,15 @@
 from rhodecode.lib.auth import HasRepoPermissionAny
 from rhodecode.lib.utils import get_repos
 from rhodecode.model import meta
-from rhodecode.model.db import Repository, User, RhodeCodeUi
+from rhodecode.model.db import Repository, User, RhodeCodeUi, CacheInvalidation
+from rhodecode.model.caching_query import FromCache
 from sqlalchemy.orm import joinedload
+from sqlalchemy.orm.session import make_transient
 from vcs import get_backend
 from vcs.utils.helpers import get_scm
 from vcs.exceptions import RepositoryError, VCSError
 from vcs.utils.lazy import LazyProperty
+import traceback
 import logging
 import os
 import time
@@ -45,12 +48,8 @@
     Mercurial Model
     """
 
-    def __init__(self, sa=None):
-        if not sa:
-            self.sa = meta.Session()
-        else:
-            self.sa = sa
-
+    def __init__(self):
+        self.sa = meta.Session()
 
     @LazyProperty
     def repos_path(self):
@@ -143,7 +142,7 @@
                             'repository.admin')(repo_name, 'get repo check'):
             return
 
-        @cache_region('long_term', 'get_repo_cached_%s' % repo_name)
+        @cache_region('long_term')
         def _get_repo(repo_name):
 
             repo_path = os.path.join(self.repos_path, repo_name)
@@ -165,13 +164,76 @@
                 .options(joinedload(Repository.user))\
                 .filter(Repository.repo_name == repo_name)\
                 .scalar()
+            make_transient(dbrepo)
             repo.dbrepo = dbrepo
             return repo
 
-        invalidate = False
+        invalidate = self._should_invalidate(repo_name)
         if invalidate:
-            log.info('INVALIDATING CACHE FOR %s', repo_name)
+            log.info('invalidating cache for repository %s', repo_name)
             region_invalidate(_get_repo, None, repo_name)
+            self._mark_invalidated(invalidate)
 
         return _get_repo(repo_name)
 
+
+
+    def mark_for_invalidation(self, repo_name):
+        """
+        Puts cache invalidation task into db for 
+        further global cache invalidation
+        
+        :param repo_name: this repo that should invalidation take place
+        """
+        log.debug('marking %s for invalidation', repo_name)
+        cache = self.sa.query(CacheInvalidation)\
+            .filter(CacheInvalidation.cache_key == repo_name).scalar()
+
+        if cache:
+            #mark this cache as inactive
+            cache.cache_active = False
+        else:
+            log.debug('cache key not found in invalidation db -> creating one')
+            cache = CacheInvalidation(repo_name)
+
+        try:
+            self.sa.add(cache)
+            self.sa.commit()
+        except:
+            log.error(traceback.format_exc())
+            self.sa.rollback()
+
+
+
+
+
+    def _should_invalidate(self, repo_name):
+        """
+        Looks up database for invalidation signals for this repo_name
+        :param repo_name:
+        """
+
+        ret = self.sa.query(CacheInvalidation)\
+            .options(FromCache('sql_cache_short',
+                           'get_invalidation_%s' % repo_name))\
+            .filter(CacheInvalidation.cache_key == repo_name)\
+            .filter(CacheInvalidation.cache_active == False)\
+            .scalar()
+
+        return ret
+
+    def _mark_invalidated(self, cache_key):
+        """
+        Marks all occurences of cache to invaldation as already invalidated
+        @param repo_name:
+        """
+        if cache_key:
+            log.debug('marking %s as already invalidated', cache_key)
+        try:
+            cache_key.cache_active = True
+            self.sa.add(cache_key)
+            self.sa.commit()
+        except:
+            log.error(traceback.format_exc())
+            self.sa.rollback()
+