comparison 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
comparison
equal deleted inserted replaced
691:7486da5f0628 692:cb0d9ce6ac5c
26 from mercurial import ui 26 from mercurial import ui
27 from rhodecode.lib import helpers as h 27 from rhodecode.lib import helpers as h
28 from rhodecode.lib.auth import HasRepoPermissionAny 28 from rhodecode.lib.auth import HasRepoPermissionAny
29 from rhodecode.lib.utils import get_repos 29 from rhodecode.lib.utils import get_repos
30 from rhodecode.model import meta 30 from rhodecode.model import meta
31 from rhodecode.model.db import Repository, User, RhodeCodeUi 31 from rhodecode.model.db import Repository, User, RhodeCodeUi, CacheInvalidation
32 from rhodecode.model.caching_query import FromCache
32 from sqlalchemy.orm import joinedload 33 from sqlalchemy.orm import joinedload
34 from sqlalchemy.orm.session import make_transient
33 from vcs import get_backend 35 from vcs import get_backend
34 from vcs.utils.helpers import get_scm 36 from vcs.utils.helpers import get_scm
35 from vcs.exceptions import RepositoryError, VCSError 37 from vcs.exceptions import RepositoryError, VCSError
36 from vcs.utils.lazy import LazyProperty 38 from vcs.utils.lazy import LazyProperty
39 import traceback
37 import logging 40 import logging
38 import os 41 import os
39 import time 42 import time
40 43
41 log = logging.getLogger(__name__) 44 log = logging.getLogger(__name__)
43 class ScmModel(object): 46 class ScmModel(object):
44 """ 47 """
45 Mercurial Model 48 Mercurial Model
46 """ 49 """
47 50
48 def __init__(self, sa=None): 51 def __init__(self):
49 if not sa: 52 self.sa = meta.Session()
50 self.sa = meta.Session()
51 else:
52 self.sa = sa
53
54 53
55 @LazyProperty 54 @LazyProperty
56 def repos_path(self): 55 def repos_path(self):
57 """ 56 """
58 Get's the repositories root path from database 57 Get's the repositories root path from database
141 """ 140 """
142 if not HasRepoPermissionAny('repository.read', 'repository.write', 141 if not HasRepoPermissionAny('repository.read', 'repository.write',
143 'repository.admin')(repo_name, 'get repo check'): 142 'repository.admin')(repo_name, 'get repo check'):
144 return 143 return
145 144
146 @cache_region('long_term', 'get_repo_cached_%s' % repo_name) 145 @cache_region('long_term')
147 def _get_repo(repo_name): 146 def _get_repo(repo_name):
148 147
149 repo_path = os.path.join(self.repos_path, repo_name) 148 repo_path = os.path.join(self.repos_path, repo_name)
150 alias = get_scm(repo_path)[0] 149 alias = get_scm(repo_path)[0]
151 150
163 dbrepo = self.sa.query(Repository)\ 162 dbrepo = self.sa.query(Repository)\
164 .options(joinedload(Repository.fork))\ 163 .options(joinedload(Repository.fork))\
165 .options(joinedload(Repository.user))\ 164 .options(joinedload(Repository.user))\
166 .filter(Repository.repo_name == repo_name)\ 165 .filter(Repository.repo_name == repo_name)\
167 .scalar() 166 .scalar()
167 make_transient(dbrepo)
168 repo.dbrepo = dbrepo 168 repo.dbrepo = dbrepo
169 return repo 169 return repo
170 170
171 invalidate = False 171 invalidate = self._should_invalidate(repo_name)
172 if invalidate: 172 if invalidate:
173 log.info('INVALIDATING CACHE FOR %s', repo_name) 173 log.info('invalidating cache for repository %s', repo_name)
174 region_invalidate(_get_repo, None, repo_name) 174 region_invalidate(_get_repo, None, repo_name)
175 self._mark_invalidated(invalidate)
175 176
176 return _get_repo(repo_name) 177 return _get_repo(repo_name)
177 178
179
180
181 def mark_for_invalidation(self, repo_name):
182 """
183 Puts cache invalidation task into db for
184 further global cache invalidation
185
186 :param repo_name: this repo that should invalidation take place
187 """
188 log.debug('marking %s for invalidation', repo_name)
189 cache = self.sa.query(CacheInvalidation)\
190 .filter(CacheInvalidation.cache_key == repo_name).scalar()
191
192 if cache:
193 #mark this cache as inactive
194 cache.cache_active = False
195 else:
196 log.debug('cache key not found in invalidation db -> creating one')
197 cache = CacheInvalidation(repo_name)
198
199 try:
200 self.sa.add(cache)
201 self.sa.commit()
202 except:
203 log.error(traceback.format_exc())
204 self.sa.rollback()
205
206
207
208
209
210 def _should_invalidate(self, repo_name):
211 """
212 Looks up database for invalidation signals for this repo_name
213 :param repo_name:
214 """
215
216 ret = self.sa.query(CacheInvalidation)\
217 .options(FromCache('sql_cache_short',
218 'get_invalidation_%s' % repo_name))\
219 .filter(CacheInvalidation.cache_key == repo_name)\
220 .filter(CacheInvalidation.cache_active == False)\
221 .scalar()
222
223 return ret
224
225 def _mark_invalidated(self, cache_key):
226 """
227 Marks all occurences of cache to invaldation as already invalidated
228 @param repo_name:
229 """
230 if cache_key:
231 log.debug('marking %s as already invalidated', cache_key)
232 try:
233 cache_key.cache_active = True
234 self.sa.add(cache_key)
235 self.sa.commit()
236 except:
237 log.error(traceback.format_exc())
238 self.sa.rollback()
239