##// END OF EJS Templates
#50 on point cache invalidation changes....
marcink -
r692:cb0d9ce6 beta
parent child Browse files
Show More
@@ -31,7 +31,7 b' from rhodecode.lib import helpers as h'
31 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
31 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
32 from rhodecode.lib.base import BaseController, render
32 from rhodecode.lib.base import BaseController, render
33 from rhodecode.model.forms import UserForm, DefaultPermissionsForm
33 from rhodecode.model.forms import UserForm, DefaultPermissionsForm
34 from rhodecode.model.permission_model import PermissionModel
34 from rhodecode.model.permission import PermissionModel
35 from rhodecode.model.user import UserModel
35 from rhodecode.model.user import UserModel
36 import formencode
36 import formencode
37 import logging
37 import logging
@@ -133,7 +133,7 b' class ReposController(BaseController):'
133 form_result = _form.to_python(dict(request.POST))
133 form_result = _form.to_python(dict(request.POST))
134 repo_model.update(repo_name, form_result)
134 repo_model.update(repo_name, form_result)
135 invalidate_cache('get_repo_cached_%s' % repo_name)
135 invalidate_cache('get_repo_cached_%s' % repo_name)
136 h.flash(_('Repository %s updated succesfully' % repo_name),
136 h.flash(_('Repository %s updated successfully' % repo_name),
137 category='success')
137 category='success')
138 changed_name = form_result['repo_name']
138 changed_name = form_result['repo_name']
139 action_logger(self.rhodecode_user, 'admin_updated_repo',
139 action_logger(self.rhodecode_user, 'admin_updated_repo',
@@ -152,7 +152,7 b' class ReposController(BaseController):'
152
152
153 except Exception:
153 except Exception:
154 log.error(traceback.format_exc())
154 log.error(traceback.format_exc())
155 h.flash(_('error occured during update of repository %s') \
155 h.flash(_('error occurred during update of repository %s') \
156 % repo_name, category='error')
156 % repo_name, category='error')
157
157
158 return redirect(url('edit_repo', repo_name=changed_name))
158 return redirect(url('edit_repo', repo_name=changed_name))
@@ -248,7 +248,7 b' class SettingsController(BaseController)'
248 """
248 """
249
249
250 # url('admin_settings_my_account')
250 # url('admin_settings_my_account')
251 c.user = UserModel(self.sa).get(c.rhodecode_user.user_id, cache=False)
251 c.user = UserModel().get(c.rhodecode_user.user_id, cache=False)
252 all_repos = self.sa.query(Repository)\
252 all_repos = self.sa.query(Repository)\
253 .filter(Repository.user_id == c.user.user_id)\
253 .filter(Repository.user_id == c.user.user_id)\
254 .order_by(func.lower(Repository.repo_name))\
254 .order_by(func.lower(Repository.repo_name))\
@@ -289,7 +289,7 b' class SettingsController(BaseController)'
289
289
290 except formencode.Invalid, errors:
290 except formencode.Invalid, errors:
291 c.user = user_model.get(c.rhodecode_user.user_id, cache=False)
291 c.user = user_model.get(c.rhodecode_user.user_id, cache=False)
292 c.user = UserModel(self.sa).get(c.rhodecode_user.user_id, cache=False)
292 c.user = UserModel().get(c.rhodecode_user.user_id, cache=False)
293 all_repos = self.sa.query(Repository)\
293 all_repos = self.sa.query(Repository)\
294 .filter(Repository.user_id == c.user.user_id)\
294 .filter(Repository.user_id == c.user.user_id)\
295 .order_by(func.lower(Repository.repo_name))\
295 .order_by(func.lower(Repository.repo_name))\
@@ -17,7 +17,6 b''
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
19 # MA 02110-1301, USA.
20 from rhodecode.lib.utils import action_logger
21 """
20 """
22 Created on April 4, 2010
21 Created on April 4, 2010
23 users controller for pylons
22 users controller for pylons
@@ -143,7 +143,7 b' def fill_perms(user):'
143 #===========================================================================
143 #===========================================================================
144 # fetch default permissions
144 # fetch default permissions
145 #===========================================================================
145 #===========================================================================
146 default_user = UserModel(sa).get_by_username('default', cache=True)
146 default_user = UserModel().get_by_username('default', cache=True)
147
147
148 default_perms = sa.query(RepoToPerm, Repository, Permission)\
148 default_perms = sa.query(RepoToPerm, Repository, Permission)\
149 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
149 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
@@ -1,16 +1,18 b''
1 from celery.decorators import task
1 from celery.decorators import task
2
2
3 import os
4 import traceback
5 from time import mktime
6
3 from operator import itemgetter
7 from operator import itemgetter
4 from pylons.i18n.translation import _
8 from pylons.i18n.translation import _
5 from rhodecode.lib.celerylib import run_task, locked_task
9 from rhodecode.lib.celerylib import run_task, locked_task
6 from rhodecode.lib.helpers import person
10 from rhodecode.lib.helpers import person
7 from rhodecode.lib.smtp_mailer import SmtpMailer
11 from rhodecode.lib.smtp_mailer import SmtpMailer
8 from rhodecode.lib.utils import OrderedDict
12 from rhodecode.lib.utils import OrderedDict
9 from time import mktime
10 import os
11 import traceback
12 from vcs.backends import get_repo
13 from vcs.backends import get_repo
13 from rhodecode.model.scm import ScmModel
14 from rhodecode.model.db import RhodeCodeUi
15
14 try:
16 try:
15 import json
17 import json
16 except ImportError:
18 except ImportError:
@@ -44,6 +46,11 b' def get_session():'
44
46
45 return sa
47 return sa
46
48
49 def get_repos_path():
50 sa = get_session()
51 q = sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
52 return q.ui_value
53
47 @task
54 @task
48 @locked_task
55 @locked_task
49 def whoosh_index(repo_location, full_index):
56 def whoosh_index(repo_location, full_index):
@@ -62,7 +69,7 b' def get_commits_stats(repo_name, ts_min_'
62
69
63 commits_by_day_author_aggregate = {}
70 commits_by_day_author_aggregate = {}
64 commits_by_day_aggregate = {}
71 commits_by_day_aggregate = {}
65 repos_path = ScmModel().repos_path
72 repos_path = get_repos_path()
66 p = os.path.join(repos_path, repo_name)
73 p = os.path.join(repos_path, repo_name)
67 repo = get_repo(p)
74 repo = get_repo(p)
68
75
@@ -271,10 +278,10 b' def create_repo_fork(form_data, cur_user'
271 from rhodecode.model.repo import RepoModel
278 from rhodecode.model.repo import RepoModel
272 from vcs import get_backend
279 from vcs import get_backend
273 log = create_repo_fork.get_logger()
280 log = create_repo_fork.get_logger()
274 repo_model = RepoModel(get_session())
281 repo_model = RepoModel()
275 repo_model.create(form_data, cur_user, just_db=True, fork=True)
282 repo_model.create(form_data, cur_user, just_db=True, fork=True)
276 repo_name = form_data['repo_name']
283 repo_name = form_data['repo_name']
277 repos_path = ScmModel().repos_path
284 repos_path = get_repos_path()
278 repo_path = os.path.join(repos_path, repo_name)
285 repo_path = os.path.join(repos_path, repo_name)
279 repo_fork_path = os.path.join(repos_path, form_data['fork_name'])
286 repo_fork_path = os.path.join(repos_path, form_data['fork_name'])
280 alias = form_data['repo_type']
287 alias = form_data['repo_type']
@@ -291,7 +298,7 b' def __get_codes_stats(repo_name):'
291 's', 'sh', 'tpl', 'txt', 'vim', 'wss', 'xhtml', 'xml', 'xsl', 'xslt', 'yaws']
298 's', 'sh', 'tpl', 'txt', 'vim', 'wss', 'xhtml', 'xml', 'xsl', 'xslt', 'yaws']
292
299
293
300
294 repos_path = ScmModel().repos_path
301 repos_path = get_repos_path()
295 p = os.path.join(repos_path, repo_name)
302 p = os.path.join(repos_path, repo_name)
296 repo = get_repo(p)
303 repo = get_repo(p)
297 tip = repo.get_changeset()
304 tip = repo.get_changeset()
@@ -89,7 +89,7 b' def action_logger(user, action, repo, ip'
89 if hasattr(user, 'user_id'):
89 if hasattr(user, 'user_id'):
90 user_obj = user
90 user_obj = user
91 elif isinstance(user, basestring):
91 elif isinstance(user, basestring):
92 user_obj = UserModel(sa).get_by_username(user, cache=False)
92 user_obj = UserModel().get_by_username(user, cache=False)
93 else:
93 else:
94 raise Exception('You have to provide user object or username')
94 raise Exception('You have to provide user object or username')
95
95
@@ -97,7 +97,7 b' def action_logger(user, action, repo, ip'
97 if repo:
97 if repo:
98 repo_name = repo.lstrip('/')
98 repo_name = repo.lstrip('/')
99
99
100 repository = RepoModel(sa).get(repo_name, cache=False)
100 repository = RepoModel().get(repo_name, cache=False)
101 if not repository:
101 if not repository:
102 raise Exception('You have to provide valid repository')
102 raise Exception('You have to provide valid repository')
103 else:
103 else:
@@ -293,12 +293,16 b' def set_rhodecode_config(config):'
293 for k, v in hgsettings.items():
293 for k, v in hgsettings.items():
294 config[k] = v
294 config[k] = v
295
295
296 def invalidate_cache(name, *args):
296 def invalidate_cache(cache_key, *args):
297 """
297 """
298 Puts cache invalidation task into db for
298 Puts cache invalidation task into db for
299 further global cache invalidation
299 further global cache invalidation
300 """
300 """
301 pass
301 from rhodecode.model.scm import ScmModel
302
303 if cache_key.startswith('get_repo_cached_'):
304 name = cache_key.split('get_repo_cached_')[-1]
305 ScmModel().mark_for_invalidation(name)
302
306
303 class EmptyChangeset(BaseChangeset):
307 class EmptyChangeset(BaseChangeset):
304 """
308 """
@@ -340,7 +344,7 b' def repo2db_mapper(initial_repo_list, re'
340 """
344 """
341
345
342 sa = meta.Session()
346 sa = meta.Session()
343 rm = RepoModel(sa)
347 rm = RepoModel()
344 user = sa.query(User).filter(User.admin == True).first()
348 user = sa.query(User).filter(User.admin == True).first()
345
349
346 for name, repo in initial_repo_list.items():
350 for name, repo in initial_repo_list.items():
@@ -90,9 +90,8 b' class Repository(Base):'
90 repo_to_perm = relation('RepoToPerm', cascade='all')
90 repo_to_perm = relation('RepoToPerm', cascade='all')
91 stats = relation('Statistics', cascade='all')
91 stats = relation('Statistics', cascade='all')
92
92
93
94 def __repr__(self):
93 def __repr__(self):
95 return "<Repository('id:%s:%s')>" % (self.repo_id, self.repo_name)
94 return "<Repository('%s:%s')>" % (self.repo_id, self.repo_name)
96
95
97 class Permission(Base):
96 class Permission(Base):
98 __tablename__ = 'permissions'
97 __tablename__ = 'permissions'
@@ -140,10 +139,17 b' class Statistics(Base):'
140
139
141 class CacheInvalidation(Base):
140 class CacheInvalidation(Base):
142 __tablename__ = 'cache_invalidation'
141 __tablename__ = 'cache_invalidation'
143 __table_args__ = {'useexisting':True}
142 __table_args__ = (UniqueConstraint('cache_key'), {'useexisting':True})
144 cache_id = Column("cache_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
143 cache_id = Column("cache_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
145 cache_key = Column("cache_key", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
144 cache_key = Column("cache_key", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
146 cache_args = Column("cache_args", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
145 cache_args = Column("cache_args", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
147 cache_active = Column("cache_active", BOOLEAN(), nullable=True, unique=None, default=None)
146 cache_active = Column("cache_active", BOOLEAN(), nullable=True, unique=None, default=False)
148
147
149
148
149 def __init__(self, cache_key, cache_args=''):
150 self.cache_key = cache_key
151 self.cache_args = cache_args
152 self.cache_active = False
153
154 def __repr__(self):
155 return "<CacheInvaidation('%s:%s')>" % (self.cache_id, self.cache_key)
@@ -33,11 +33,8 b' log = logging.getLogger(__name__)'
33
33
34 class PermissionModel(object):
34 class PermissionModel(object):
35
35
36 def __init__(self, sa=None):
36 def __init__(self):
37 if not sa:
37 self.sa = Session()
38 self.sa = Session()
39 else:
40 self.sa = sa
41
38
42 def get_permission(self, permission_id, cache=False):
39 def get_permission(self, permission_id, cache=False):
43 perm = self.sa.query(Permission)
40 perm = self.sa.query(Permission)
@@ -36,11 +36,8 b' log = logging.getLogger(__name__)'
36
36
37 class RepoModel(object):
37 class RepoModel(object):
38
38
39 def __init__(self, sa=None):
39 def __init__(self):
40 if not sa:
40 self.sa = Session()
41 self.sa = Session()
42 else:
43 self.sa = sa
44
41
45 def get(self, repo_id, cache=False):
42 def get(self, repo_id, cache=False):
46 repo = self.sa.query(Repository)\
43 repo = self.sa.query(Repository)\
@@ -67,7 +64,7 b' class RepoModel(object):'
67 #update permissions
64 #update permissions
68 for username, perm in form_data['perms_updates']:
65 for username, perm in form_data['perms_updates']:
69 r2p = self.sa.query(RepoToPerm)\
66 r2p = self.sa.query(RepoToPerm)\
70 .filter(RepoToPerm.user == UserModel(self.sa).get_by_username(username, cache=False))\
67 .filter(RepoToPerm.user == UserModel().get_by_username(username, cache=False))\
71 .filter(RepoToPerm.repository == self.get(repo_name))\
68 .filter(RepoToPerm.repository == self.get(repo_name))\
72 .one()
69 .one()
73
70
@@ -80,7 +77,7 b' class RepoModel(object):'
80 for username, perm in form_data['perms_new']:
77 for username, perm in form_data['perms_new']:
81 r2p = RepoToPerm()
78 r2p = RepoToPerm()
82 r2p.repository = self.get(repo_name)
79 r2p.repository = self.get(repo_name)
83 r2p.user = UserModel(self.sa).get_by_username(username, cache=False)
80 r2p.user = UserModel().get_by_username(username, cache=False)
84
81
85 r2p.permission_id = self.sa.query(Permission).filter(
82 r2p.permission_id = self.sa.query(Permission).filter(
86 Permission.permission_name == perm)\
83 Permission.permission_name == perm)\
@@ -134,7 +131,7 b' class RepoModel(object):'
134 #create default permission
131 #create default permission
135 repo_to_perm = RepoToPerm()
132 repo_to_perm = RepoToPerm()
136 default = 'repository.read'
133 default = 'repository.read'
137 for p in UserModel(self.sa).get_by_username('default', cache=False).user_perms:
134 for p in UserModel().get_by_username('default', cache=False).user_perms:
138 if p.permission.permission_name.startswith('repository.'):
135 if p.permission.permission_name.startswith('repository.'):
139 default = p.permission.permission_name
136 default = p.permission.permission_name
140 break
137 break
@@ -146,7 +143,7 b' class RepoModel(object):'
146 .one().permission_id
143 .one().permission_id
147
144
148 repo_to_perm.repository_id = new_repo.repo_id
145 repo_to_perm.repository_id = new_repo.repo_id
149 repo_to_perm.user_id = UserModel(self.sa).get_by_username('default', cache=False).user_id
146 repo_to_perm.user_id = UserModel().get_by_username('default', cache=False).user_id
150
147
151 self.sa.add(repo_to_perm)
148 self.sa.add(repo_to_perm)
152 self.sa.commit()
149 self.sa.commit()
@@ -28,12 +28,15 b' 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
@@ -45,12 +48,8 b' class ScmModel(object):'
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):
@@ -143,7 +142,7 b' class ScmModel(object):'
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)
@@ -165,13 +164,76 b' class ScmModel(object):'
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
@@ -36,11 +36,8 b' class DefaultUserException(Exception):pa'
36
36
37 class UserModel(object):
37 class UserModel(object):
38
38
39 def __init__(self, sa=None):
39 def __init__(self):
40 if not sa:
40 self.sa = Session()
41 self.sa = Session()
42 else:
43 self.sa = sa
44
41
45 def get(self, user_id, cache=False):
42 def get(self, user_id, cache=False):
46 user = self.sa.query(User)
43 user = self.sa.query(User)
General Comments 0
You need to be logged in to leave comments. Login now