[IMP] *: optimise loading of home page

Fix outstanding query to make a positive `state` filtering, instead of
negative, matching 3b52b1aace8674259812a76b1566260937dbcacb.

Also manually create a map of stagings (grouped by branch) sharing a
single prefetch set.

For odoo the mergebot home page has 12 branches in the odoo project
and 8 in spreadsheet, 6 stagings each. This means 120 queries to
retrieve all the heads (Odoo stagings have 5 heads and spreadsheet
have 1, but that seems immaterial).

By fixing `_compute_statuses` and creating a single prefetch set for
all stagings of all branches we can fetch all the commits in a single
query instead of 120.
This commit is contained in:
Xavier Morel 2023-07-06 10:28:52 +02:00
parent 81ce4ea02b
commit 5bce73c97d
4 changed files with 39 additions and 10 deletions

View File

@ -10,8 +10,7 @@
<xpath expr="//div[@id='alerts']" position="inside">
<t t-if="env['runbot_merge.pull_requests'].check_access_rights('read', False)">
<t t-set="outstanding" t-value="env['runbot_merge.pull_requests'].search_count([
('source_id', '!=', False),
('state', 'not in', ['merged', 'closed']),
('state', 'in', ['opened', 'validated', 'approved', 'ready', 'error']),
('source_id.merge_date', '&lt;', datetime.datetime.now() - relativedelta(days=3)),
])"/>
<div t-if="outstanding != 0" class="alert col-md-12 alert-warning mb-0">

View File

@ -13,8 +13,25 @@ LIMIT = 20
class MergebotDashboard(Controller):
@route('/runbot_merge', auth="public", type="http", website=True, sitemap=True)
def dashboard(self):
projects = request.env['runbot_merge.project'].with_context(active_test=False).sudo().search([])
stagings = {
branch: projects.env['runbot_merge.stagings'].search([
('target', '=', branch.id)], order='staged_at desc', limit=6)
for project in projects
for branch in project.branch_ids
if branch.active
}
prefetch_set = list({
id
for stagings in stagings.values()
for id in stagings.ids
})
for st in stagings.values():
st._prefetch_ids = prefetch_set
return request.render('runbot_merge.dashboard', {
'projects': request.env['runbot_merge.project'].with_context(active_test=False).sudo().search([]),
'projects': projects,
'stagings_map': stagings,
})
@route('/runbot_merge/<int:branch_id>', auth='public', type='http', website=True, sitemap=False)

View File

@ -1813,12 +1813,25 @@ class Stagings(models.Model):
(repo, context, state, url)
"""
Commits = self.env['runbot_merge.commit']
heads = {
head: repo
for st in self
for repo, head in json.loads(st.heads).items()
if not repo.endswith('^')
}
all_heads = Commits.search([('sha', 'in', list(heads))])
commits_map = {commit.sha: commit.id for commit in all_heads}
for st in self:
heads = {
head: repo for repo, head in json.loads(st.heads).items()
if not repo.endswith('^')
}
commits = st.head_ids = Commits.search([('sha', 'in', list(heads.keys()))])
commits = st.head_ids = Commits._browse(
self.env,
tuple(
commits_map[h]
for repo, h in json.loads(st.heads).items()
if not repo.endswith('^')
),
all_heads._prefetch_ids
)
if st.statuses_cache:
st.statuses = json.loads(st.statuses_cache)
continue

View File

@ -72,7 +72,7 @@
<t t-call="website.layout">
<div id="wrap"><div class="container-fluid">
<t t-call="runbot_merge.alerts"/>
<section t-foreach="projects.with_context(active_test=False)" t-as="project" class="row">
<section t-foreach="projects" t-as="project" class="row">
<h1 class="col-md-12"><t t-esc="project.name"/></h1>
<div class="col-md-12">
key:
@ -154,7 +154,7 @@
<template id="stagings" name="mergebot branch stagings">
<t t-set="repo_statuses" t-value="branch.project_id.repo_ids.having_branch(branch).status_ids"/>
<ul class="list-unstyled stagings">
<t t-foreach="branch.env['runbot_merge.stagings'].search([('target', '=', branch.id)], order='staged_at desc', limit=6)" t-as="staging">
<t t-foreach="stagings_map[branch]" t-as="staging">
<t t-set="success" t-value="staging.state == 'success'"/>
<t t-set="failure" t-value="staging.state == 'failure'"/>
<t t-set="pending" t-value="staging.active and (not staging.state or staging.state == 'pending')"/>