Minimize the queries used when retrieve builds. Previously, we'd call out to SQL extra times per build.

This commit is contained in:
Joseph Schorr 2015-05-07 21:11:15 -04:00
parent e99ae67e58
commit 3627de103c
5 changed files with 34 additions and 17 deletions

View file

@ -2291,10 +2291,12 @@ def load_token_data(code):
def _get_build_base_query(): def _get_build_base_query():
return (RepositoryBuild return (RepositoryBuild
.select(RepositoryBuild, RepositoryBuildTrigger, BuildTriggerService, Repository, .select(RepositoryBuild, RepositoryBuildTrigger, BuildTriggerService, Repository,
Namespace) Namespace, User)
.join(Repository) .join(Repository)
.join(Namespace, on=(Repository.namespace_user == Namespace.id)) .join(Namespace, on=(Repository.namespace_user == Namespace.id))
.switch(RepositoryBuild) .switch(RepositoryBuild)
.join(User, JOIN_LEFT_OUTER)
.switch(RepositoryBuild)
.join(RepositoryBuildTrigger, JOIN_LEFT_OUTER) .join(RepositoryBuildTrigger, JOIN_LEFT_OUTER)
.join(BuildTriggerService, JOIN_LEFT_OUTER) .join(BuildTriggerService, JOIN_LEFT_OUTER)
.order_by(RepositoryBuild.started.desc())) .order_by(RepositoryBuild.started.desc()))

View file

@ -45,7 +45,7 @@ def user_view(user):
'is_robot': user.robot, 'is_robot': user.robot,
} }
def trigger_view(trigger, can_read=False, can_admin=False): def trigger_view(trigger, can_read=False, can_admin=False, for_build=False):
if trigger and trigger.uuid: if trigger and trigger.uuid:
build_trigger = BuildTriggerHandler.get_handler(trigger) build_trigger = BuildTriggerHandler.get_handler(trigger)
build_source = build_trigger.config.get('build_source') build_source = build_trigger.config.get('build_source')
@ -55,17 +55,28 @@ def trigger_view(trigger, can_read=False, can_admin=False):
if can_admin: if can_admin:
can_read = True can_read = True
return { is_connected_user = False
'service': trigger.service.name, if (can_admin and get_authenticated_user() and
'build_source': build_source if can_read else None, trigger.connected_user_id == get_authenticated_user().id):
'config': build_trigger.config if can_admin else {}, is_connected_user = True
trigger_data = {
'id': trigger.uuid, 'id': trigger.uuid,
'connected_user': trigger.connected_user.username, 'service': trigger.service.name,
'is_active': build_trigger.is_active(), 'is_active': build_trigger.is_active(),
'pull_robot': user_view(trigger.pull_robot) if trigger.pull_robot else None,
'build_source': build_source if can_read else None,
'repository_url': repo_url if can_read else None, 'repository_url': repo_url if can_read else None,
'config': build_trigger.config if can_admin else {},
'is_connected_user': is_connected_user,
} }
if not for_build and can_admin and trigger.pull_robot:
trigger_data['pull_robot'] = user_view(trigger.pull_robot)
return trigger_data
return None return None
@ -111,7 +122,7 @@ def build_status_view(build_obj):
'tags': job_config.get('docker_tags', []), 'tags': job_config.get('docker_tags', []),
'manual_user': job_config.get('manual_user', None), 'manual_user': job_config.get('manual_user', None),
'is_writer': can_write, 'is_writer': can_write,
'trigger': trigger_view(build_obj.trigger, can_read, can_admin), 'trigger': trigger_view(build_obj.trigger, can_read, can_admin, for_build=True),
'trigger_metadata': job_config.get('trigger_metadata', None) if can_read else None, 'trigger_metadata': job_config.get('trigger_metadata', None) if can_read else None,
'resource_key': build_obj.resource_key, 'resource_key': build_obj.resource_key,
'pull_robot': user_view(build_obj.pull_robot) if build_obj.pull_robot else None, 'pull_robot': user_view(build_obj.pull_robot) if build_obj.pull_robot else None,

View file

@ -146,7 +146,7 @@
<i class="fa fa-unlock-alt"></i> View Credentials <i class="fa fa-unlock-alt"></i> View Credentials
</span> </span>
<span class="cor-option" option-click="askRunTrigger(trigger)" <span class="cor-option" option-click="askRunTrigger(trigger)"
ng-class="trigger.connected_user == user.username ? '' : 'disabled'"> ng-class="trigger.is_connected_user ? '' : 'disabled'">
<i class="fa fa-chevron-right"></i> Run Trigger Now <i class="fa fa-chevron-right"></i> Run Trigger Now
</span> </span>
<span class="cor-option" option-click="askDeleteTrigger(trigger)"> <span class="cor-option" option-click="askDeleteTrigger(trigger)">

View file

@ -197,9 +197,9 @@ angular.module('quay').directive('repoPanelBuilds', function () {
}; };
$scope.askRunTrigger = function(trigger) { $scope.askRunTrigger = function(trigger) {
if ($scope.user.username != trigger.connected_user) { if (!trigger.is_connected_user) {
bootbox.alert('For security reasons, only user "' + trigger.connected_user + bootbox.alert('For security reasons, only the user that created this trigger can ' +
'" can manually invoke this trigger'); 'manually invoke this trigger');
return; return;
} }

View file

@ -6,6 +6,8 @@ import json as py_json
from urllib import urlencode from urllib import urlencode
from urlparse import urlparse, urlunparse, parse_qs from urlparse import urlparse, urlunparse, parse_qs
from playhouse.test_utils import assert_query_count
from endpoints.api import api_bp, api from endpoints.api import api_bp, api
from endpoints.building import PreparedBuild from endpoints.building import PreparedBuild
from endpoints.webhooks import webhooks from endpoints.webhooks import webhooks
@ -1544,16 +1546,18 @@ class TestRepoBuilds(ApiTestCase):
def test_getrepo_nobuilds(self): def test_getrepo_nobuilds(self):
self.login(ADMIN_ACCESS_USER) self.login(ADMIN_ACCESS_USER)
json = self.getJsonResponse(RepositoryBuildList, with assert_query_count(4):
params=dict(repository=ADMIN_ACCESS_USER + '/simple')) json = self.getJsonResponse(RepositoryBuildList,
params=dict(repository=ADMIN_ACCESS_USER + '/simple'))
assert len(json['builds']) == 0 assert len(json['builds']) == 0
def test_getrepobuilds(self): def test_getrepobuilds(self):
self.login(ADMIN_ACCESS_USER) self.login(ADMIN_ACCESS_USER)
json = self.getJsonResponse(RepositoryBuildList, with assert_query_count(4):
params=dict(repository=ADMIN_ACCESS_USER + '/building')) json = self.getJsonResponse(RepositoryBuildList,
params=dict(repository=ADMIN_ACCESS_USER + '/building'))
assert len(json['builds']) > 0 assert len(json['builds']) > 0
build = json['builds'][-1] build = json['builds'][-1]