[IMP] optimizations to runbot controller

This commit is contained in:
Gery Debongnie 2014-07-17 14:27:05 +02:00
parent 06fe91b443
commit 40a1d8010b
2 changed files with 38 additions and 30 deletions

View File

@ -15,6 +15,7 @@ import subprocess
import time import time
import sys import sys
from collections import OrderedDict from collections import OrderedDict
import itertools
import dateutil.parser import dateutil.parser
import requests import requests
@ -123,6 +124,9 @@ def s2human(time):
return str(int(time / delay)) + desc return str(int(time / delay)) + desc
return str(int(time)) + "s" return str(int(time)) + "s"
def flatten(list_of_lists):
return itertools.chain.from_iterable(list_of_lists)
#---------------------------------------------------------- #----------------------------------------------------------
# RunBot Models # RunBot Models
#---------------------------------------------------------- #----------------------------------------------------------
@ -222,6 +226,7 @@ class runbot_repo(osv.osv):
_logger.debug('repo %s updating branches', repo.name) _logger.debug('repo %s updating branches', repo.name)
Build = self.pool['runbot.build'] Build = self.pool['runbot.build']
Branch = self.pool['runbot.branch']
if not os.path.isdir(os.path.join(repo.path)): if not os.path.isdir(os.path.join(repo.path)):
os.makedirs(repo.path) os.makedirs(repo.path)
@ -245,18 +250,18 @@ class runbot_repo(osv.osv):
for name, sha, date, author, subject in refs: for name, sha, date, author, subject in refs:
# create or get branch # create or get branch
branch_ids = self.pool['runbot.branch'].search(cr, uid, [('repo_id', '=', repo.id), ('name', '=', name)]) branch_ids = Branch.search(cr, uid, [('repo_id', '=', repo.id), ('name', '=', name)])
if branch_ids: if branch_ids:
branch_id = branch_ids[0] branch_id = branch_ids[0]
else: else:
_logger.debug('repo %s found new branch %s', repo.name, name) _logger.debug('repo %s found new branch %s', repo.name, name)
branch_id = self.pool['runbot.branch'].create(cr, uid, {'repo_id': repo.id, 'name': name}) branch_id = Branch.create(cr, uid, {'repo_id': repo.id, 'name': name})
branch = self.pool['runbot.branch'].browse(cr, uid, [branch_id], context=context)[0] branch = Branch.browse(cr, uid, [branch_id], context=context)[0]
# skip build for old branches # skip build for old branches
if dateutil.parser.parse(date[:19]) + datetime.timedelta(30) < datetime.datetime.now(): if dateutil.parser.parse(date[:19]) + datetime.timedelta(30) < datetime.datetime.now():
continue continue
# create build (and mark previous builds as skipped) if not found # create build (and mark previous builds as skipped) if not found
build_ids = self.pool['runbot.build'].search(cr, uid, [('branch_id', '=', branch.id), ('name', '=', sha)]) build_ids = Build.search(cr, uid, [('branch_id', '=', branch.id), ('name', '=', sha)])
if not build_ids: if not build_ids:
if not branch.sticky: if not branch.sticky:
to_be_skipped_ids = Build.search(cr, uid, [('branch_id', '=', branch.id), ('state', '=', 'pending')]) to_be_skipped_ids = Build.search(cr, uid, [('branch_id', '=', branch.id), ('state', '=', 'pending')])
@ -302,6 +307,7 @@ class runbot_repo(osv.osv):
pending_ids = Build.search(cr, uid, domain + [('state', '=', 'pending')], order="sequence", limit=1) pending_ids = Build.search(cr, uid, domain + [('state', '=', 'pending')], order="sequence", limit=1)
pending_build = Build.browse(cr, uid, pending_ids[0]) pending_build = Build.browse(cr, uid, pending_ids[0])
print 'scheduling build', pending_build
pending_build.schedule() pending_build.schedule()
# compute the number of testing and pending jobs again # compute the number of testing and pending jobs again
@ -465,11 +471,10 @@ class runbot_build(osv.osv):
('repo_id','=',build.repo_id.duplicate_id.id), ('repo_id','=',build.repo_id.duplicate_id.id),
('name', '=', build.name), ('name', '=', build.name),
('duplicate_id', '=', False), ('duplicate_id', '=', False),
('result', '!=', 'skipped') '|', ('result', '=', False), ('result', '!=', 'skipped')
] ]
print domain duplicate_ids = self.search(cr, uid, domain, context=context)
duplicate_ids = self.search(cr, uid, domain)
print duplicate_ids
if len(duplicate_ids): if len(duplicate_ids):
extra_info.update({'state': 'duplicate', 'duplicate_id': duplicate_ids[0]}) extra_info.update({'state': 'duplicate', 'duplicate_id': duplicate_ids[0]})
self.write(cr, uid, [duplicate_ids[0]], {'duplicate_id': build_id}) self.write(cr, uid, [duplicate_ids[0]], {'duplicate_id': build_id})
@ -892,38 +897,41 @@ class RunbotController(http.Controller):
} }
if repo: if repo:
# filters
filters = {key: post.get(key, '1') for key in ['pending', 'testing', 'running', 'done']} filters = {key: post.get(key, '1') for key in ['pending', 'testing', 'running', 'done']}
domain = [('repo_id','=',repo.id)] domain = [('repo_id','=',repo.id)]
domain += [('state', '!=', key) for key, value in filters.iteritems() if value == '0'] domain += [('state', '!=', key) for key, value in filters.iteritems() if value == '0']
if search: if search:
domain += [('dest','ilike',search)] domain += [('dest','ilike',search)]
context['filters'] = filters
qu = QueryURL('/runbot/repo/'+slug(repo), search=search, limit=limit, refresh=refresh, **filters)
context['qu'] = qu
build_ids = build_obj.search(cr, uid, domain + [('branch_id.sticky','=',False)], limit=int(limit)) non_sticky_builds = build_obj.search(cr, uid, domain + [('branch_id.sticky','=',False)], limit=int(limit))
branch_ids = branch_obj.search(cr, uid, [('sticky', '=', True)]) branch_ids = branch_obj.search(cr, uid, domain + [('sticky', '=', True)])
if build_ids: if non_sticky_builds:
q = """ q = """
SELECT br.id FROM runbot_branch br INNER JOIN runbot_build bu ON br.id=bu.branch_id WHERE bu.id in %s SELECT br.id FROM runbot_branch br INNER JOIN runbot_build bu ON br.id=bu.branch_id WHERE bu.id in %s
ORDER BY bu.sequence DESC ORDER BY bu.sequence DESC
""" """
cr.execute(q, (tuple(build_ids),)) cr.execute(q, (tuple(non_sticky_builds),))
branch_ids += OrderedDict.fromkeys(br[0] for br in cr.fetchall()).keys() branch_ids += OrderedDict.fromkeys(br[0] for br in cr.fetchall()).keys()
branches = branch_obj.browse(cr, uid, branch_ids, context=request.context) branches = branch_obj.browse(cr, uid, branch_ids, context=request.context)
context['branches'] = [] build_by_branch_ids = {b: build_obj.search(cr, uid, [('branch_id','=',b)], limit=4) for b in branch_ids}
build_ids = flatten(build_by_branch_ids.values())
build_dict = {build.id: build for build in build_obj.browse(cr, uid, build_ids, context=request.context) }
for branch in branches: def branch_info(branch):
build_ids = build_obj.search(cr, uid, [('branch_id','=',branch.id)], limit=4) return {
branch.builds = build_obj.browse(cr, uid, build_ids, context=request.context) 'branch': branch,
context['branches'].append(branch) 'builds': [build_dict[build_id] for build_id in build_by_branch_ids[branch.id]]
}
# stats context.update({
context['testing'] = build_obj.search_count(cr, uid, [('repo_id','=',repo.id), ('state','=','testing')]) 'branches': [branch_info(b) for b in branches],
context['running'] = build_obj.search_count(cr, uid, [('repo_id','=',repo.id), ('state','=','running')]) 'testing': build_obj.search_count(cr, uid, [('repo_id','=',repo.id), ('state','=','testing')]),
context['pending'] = build_obj.search_count(cr, uid, [('repo_id','=',repo.id), ('state','=','pending')]) 'running': build_obj.search_count(cr, uid, [('repo_id','=',repo.id), ('state','=','running')]),
'pending': build_obj.search_count(cr, uid, [('repo_id','=',repo.id), ('state','=','pending')]),
'qu': QueryURL('/runbot/repo/'+slug(repo), search=search, limit=limit, refresh=refresh, **filters),
'filters': filters,
})
return request.render("runbot.repo", context) return request.render("runbot.repo", context)

View File

@ -350,14 +350,14 @@
</tr> </tr>
<tr t-foreach="branches" t-as="br"> <tr t-foreach="branches" t-as="br">
<td> <td>
<i t-if="br.sticky" class="fa fa-star"/> <i t-if="br['branch'].sticky" class="fa fa-star"/>
<b t-esc="br.branch_name"/> <b t-esc="br['branch'].branch_name"/>
<small><t t-esc="s2h(br.builds[0].job_age)"/></small><br/> <small><t t-esc="s2h(br['builds'][0].job_age)"/></small><br/>
<div class="btn-group btn-group-xs"> <div class="btn-group btn-group-xs">
<a t-attf-href="{{br.branch_url}}" class="btn btn-default btn-xs">Branch or pull <i class="fa fa-github"/></a> <a t-attf-href="{{br['branch'].branch_url}}" class="btn btn-default btn-xs">Branch or pull <i class="fa fa-github"/></a>
</div> </div>
</td> </td>
<t t-foreach="br.builds" t-as="bu"> <t t-foreach="br['builds']" t-as="bu">
<t t-if="bu.state=='pending'"><t t-set="klass">default</t></t> <t t-if="bu.state=='pending'"><t t-set="klass">default</t></t>
<t t-if="bu.state=='testing'"><t t-set="klass">info</t></t> <t t-if="bu.state=='testing'"><t t-set="klass">info</t></t>
<t t-if="bu.state in ['running','done'] and bu.result == 'ko'"><t t-set="klass">danger</t></t> <t t-if="bu.state in ['running','done'] and bu.result == 'ko'"><t t-set="klass">danger</t></t>