Changeset - 20a094053606
[Not reviewed]
default
0 4 0
Mads Kiilerich - 10 years ago 2016-03-14 16:17:46
madski@unity3d.com
pullrequests: optimize iteration over reviewers - avoid fetching users one by one

.reviewers was mainly used for iteration and then dereferencing .user one by
one. That gave lots of queries and round trips to the database and was slow.

Instead, do something else. Either query directly or use a new method for
getting the list of reviewer users.

Reviewers will explicitly be shown in the order they have been added (assuming
database id's are monotonic).
4 files changed with 18 insertions and 7 deletions:
0 comments (0 inline, 0 general)
kallithea/controllers/pullrequests.py
Show inline comments
 
@@ -179,14 +179,17 @@ class PullrequestsController(BaseRepoCon
 

	
 
    def _get_is_allowed_change_status(self, pull_request):
 
        if pull_request.is_closed():
 
            return False
 

	
 
        owner = self.authuser.user_id == pull_request.user_id
 
        reviewer = self.authuser.user_id in [x.user_id for x in
 
                                                   pull_request.reviewers]
 
        reviewer = PullRequestReviewers.query() \
 
            .filter(PullRequestReviewers.pull_request == pull_request) \
 
            .filter(PullRequestReviewers.user_id == self.authuser.user_id) \
 
            .count() != 0
 

	
 
        return self.authuser.admin or owner or reviewer
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def show_all(self, repo_name):
kallithea/model/changeset_status.py
Show inline comments
 
@@ -95,20 +95,20 @@ class ChangesetStatusModel(BaseModel):
 
            cs_statuses[st.author.username] = st
 

	
 
        # collect votes from official reviewers
 
        pull_request_reviewers = []
 
        pull_request_pending_reviewers = []
 
        relevant_statuses = []
 
        for r in pull_request.reviewers:
 
            st = cs_statuses.get(r.user.username)
 
        for user in pull_request.get_reviewer_users():
 
            st = cs_statuses.get(user.username)
 
            relevant_statuses.append(st)
 
            if not st or st.status in (ChangesetStatus.STATUS_NOT_REVIEWED,
 
                                       ChangesetStatus.STATUS_UNDER_REVIEW):
 
                st = None
 
                pull_request_pending_reviewers.append(r.user)
 
            pull_request_reviewers.append((r.user, st))
 
                pull_request_pending_reviewers.append(user)
 
            pull_request_reviewers.append((user, st))
 

	
 
        result = self._calculate_status(relevant_statuses)
 

	
 
        return (pull_request_reviewers,
 
                pull_request_pending_reviewers,
 
                result)
kallithea/model/comment.py
Show inline comments
 
@@ -136,13 +136,13 @@ class ChangesetCommentsModel(BaseModel):
 
            recipients = ChangesetComment.get_users(pull_request_id=
 
                                                pull_request.pull_request_id)
 
            # add pull request author
 
            recipients += [pull_request.owner]
 

	
 
            # add the reviewers to notification
 
            recipients += [x.user for x in pull_request.reviewers]
 
            recipients += pull_request.get_reviewer_users()
 

	
 
            #set some variables for email notification
 
            email_kwargs = {
 
                'pr_title': pull_request.title,
 
                'pr_nice_id': pull_request.nice_id(),
 
                'status_change': status_change,
kallithea/model/db.py
Show inline comments
 
@@ -2319,12 +2319,20 @@ class PullRequest(Base, BaseModel):
 
    org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
 
    other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
 
    statuses = relationship('ChangesetStatus', order_by='ChangesetStatus.changeset_status_id')
 
    comments = relationship('ChangesetComment', order_by='ChangesetComment.comment_id',
 
                             cascade="all, delete-orphan")
 

	
 
    def get_reviewer_users(self):
 
        """Like .reviewers, but actually returning the users"""
 
        return User.query() \
 
            .join(PullRequestReviewers) \
 
            .filter(PullRequestReviewers.pull_request == self) \
 
            .order_by(PullRequestReviewers.pull_requests_reviewers_id) \
 
            .all()
 

	
 
    def is_closed(self):
 
        return self.status == self.STATUS_CLOSED
 

	
 
    def user_review_status(self, user_id):
 
        """Return the user's latest status votes on PR"""
 
        # note: no filtering on repo - that would be redundant
0 comments (0 inline, 0 general)