@@ -2049,193 +2049,199 @@ class CacheInvalidation(Base, BaseModel)
cache_args = Column(String(255, convert_unicode=False))
# instance sets cache_active True when it is caching, other instances set
# cache_active to False to indicate that this cache is invalid
cache_active = Column(Boolean(), nullable=True, unique=None, default=False)
def __init__(self, cache_key, repo_name=''):
self.cache_key = cache_key
self.cache_args = repo_name
self.cache_active = False
def __unicode__(self):
return u"<%s('%s:%s[%s]')>" % (
self.__class__.__name__,
self.cache_id, self.cache_key, self.cache_active)
def _cache_key_partition(self):
prefix, repo_name, suffix = self.cache_key.partition(self.cache_args)
return prefix, repo_name, suffix
def get_prefix(self):
"""
get prefix that might have been used in _get_cache_key to
generate self.cache_key. Only used for informational purposes
in repo_edit.html.
# prefix, repo_name, suffix
return self._cache_key_partition()[0]
def get_suffix(self):
get suffix that might have been used in _get_cache_key to
return self._cache_key_partition()[2]
@classmethod
def clear_cache(cls):
Delete all cache keys from database.
Should only be run when all instances are down and all entries thus stale.
cls.query().delete()
Session().commit()
def _get_cache_key(cls, key):
Wrapper for generating a unique cache key for this instance and "key".
key must / will start with a repo_name which will be stored in .cache_args .
import kallithea
prefix = kallithea.CONFIG.get('instance_id', '')
return "%s%s" % (prefix, key)
def set_invalidate(cls, repo_name, delete=False):
Mark all caches of a repo as invalid in the database.
inv_objs = Session().query(cls).filter(cls.cache_args == repo_name).all()
log.debug('for repo %s got %s invalidation objects',
safe_str(repo_name), inv_objs)
for inv_obj in inv_objs:
log.debug('marking %s key for invalidation based on repo_name=%s',
inv_obj, safe_str(repo_name))
if delete:
Session().delete(inv_obj)
else:
inv_obj.cache_active = False
Session().add(inv_obj)
def test_and_set_valid(cls, repo_name, kind, valid_cache_keys=None):
Mark this cache key as active and currently cached.
Return True if the existing cache registration still was valid.
Return False to indicate that it had been invalidated and caches should be refreshed.
key = (repo_name + '_' + kind) if kind else repo_name
cache_key = cls._get_cache_key(key)
if valid_cache_keys and cache_key in valid_cache_keys:
return True
inv_obj = cls.query().filter(cls.cache_key == cache_key).scalar()
if not inv_obj:
inv_obj = CacheInvalidation(cache_key, repo_name)
if inv_obj.cache_active:
inv_obj.cache_active = True
try:
except exc.IntegrityError:
raise
# TOCTOU - another thread added the key at the same time; no further action required
return False
def get_valid_cache_keys(cls):
Return opaque object with information of which caches still are valid
and can be used without checking for invalidation.
return set(inv_obj.cache_key for inv_obj in cls.query().filter(cls.cache_active).all())
class ChangesetComment(Base, BaseModel):
__tablename__ = 'changeset_comments'
__table_args__ = (
Index('cc_revision_idx', 'revision'),
Index('cc_pull_request_id_idx', 'pull_request_id'),
{'extend_existing': True, 'mysql_engine': 'InnoDB',
'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
)
comment_id = Column(Integer(), nullable=False, unique=True, primary_key=True)
repo_id = Column(Integer(), ForeignKey('repositories.repo_id'), nullable=False)
revision = Column(String(40))
pull_request_id = Column(Integer(), ForeignKey('pull_requests.pull_request_id'))
line_no = Column(Unicode(10))
f_path = Column(Unicode(1000))
user_id = Column(Integer(), ForeignKey('users.user_id'), nullable=False)
text = Column(UnicodeText(25000), nullable=False)
created_on = Column(DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
modified_at = Column(DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
author = relationship('User')
repo = relationship('Repository')
# status_change is frequently used directly in templates - make it a lazy
# join to avoid fetching each related ChangesetStatus on demand.
# There will only be one ChangesetStatus referencing each comment so the join will not explode.
status_change = relationship('ChangesetStatus',
cascade="all, delete-orphan", lazy='joined')
pull_request = relationship('PullRequest')
def get_users(cls, revision=None, pull_request_id=None):
Returns user associated with this ChangesetComment. ie those
who actually commented
:param cls:
:param revision:
q = Session().query(User)\
.join(ChangesetComment.author)
if revision is not None:
q = q.filter(cls.revision == revision)
elif pull_request_id is not None:
q = q.filter(cls.pull_request_id == pull_request_id)
return q.all()
def url(self):
anchor = "comment-%s" % self.comment_id
import kallithea.lib.helpers as h
if self.revision:
return h.url('changeset_home', repo_name=self.repo.repo_name, revision=self.revision, anchor=anchor)
elif self.pull_request_id is not None:
return self.pull_request.url(anchor=anchor)
class ChangesetStatus(Base, BaseModel):
__tablename__ = 'changeset_statuses'
Index('cs_revision_idx', 'revision'),
Index('cs_version_idx', 'version'),
Index('cs_pull_request_id_idx', 'pull_request_id'),
Index('cs_changeset_comment_id_idx', 'changeset_comment_id'),
Index('cs_pull_request_id_user_id_version_idx', 'pull_request_id', 'user_id', 'version'),
UniqueConstraint('repo_id', 'revision', 'version'),
'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
STATUS_APPROVED = 'approved'
STATUS_REJECTED = 'rejected'
STATUS_UNDER_REVIEW = 'under_review'
STATUSES = [
(STATUS_NOT_REVIEWED, _("Not reviewed")), # (no icon) and default
(STATUS_APPROVED, _("Approved")),
(STATUS_REJECTED, _("Rejected")),
(STATUS_UNDER_REVIEW, _("Under review")),
]
changeset_status_id = Column(Integer(), nullable=False, unique=True, primary_key=True)
user_id = Column(Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
revision = Column(String(40), nullable=False)
status = Column(String(128), nullable=False, default=DEFAULT)
changeset_comment_id = Column(Integer(), ForeignKey('changeset_comments.comment_id'), nullable=False)
modified_at = Column(DateTime(), nullable=False, default=datetime.datetime.now)
version = Column(Integer(), nullable=False, default=0)
Status change: