[IMP] runbot: always keep one empty slot when assigning sheduled

Nightly build have a low priority but once they have a slot, they keep it.
When pushing a branch or asking robodoo to nicelly merge a branch for the
third time at 22:00, there may be no slot left since all the nightly build are created.

This commit will only assign scheduled build if there is no other build to create and
will always keep a free slot for other builds.
This commit is contained in:
Xavier-Do 2019-06-13 10:51:20 +02:00 committed by XavierDo
parent 86ffeac589
commit bdc6506ede

View File

@ -370,32 +370,44 @@ class runbot_repo(models.Model):
if available_slots > 0: if available_slots > 0:
if assignable_slots > 0: # note: slots have been addapt to be able to force host on pending build. Normally there is no pending with host. if assignable_slots > 0: # note: slots have been addapt to be able to force host on pending build. Normally there is no pending with host.
# commit transaction to reduce the critical section duration # commit transaction to reduce the critical section duration
self.env.cr.commit() def allocate_builds(where_clause, limit):
# self-assign to be sure that another runbot instance cannot self assign the same builds self.env.cr.commit()
query = """UPDATE # self-assign to be sure that another runbot instance cannot self assign the same builds
runbot_build query = """UPDATE
SET runbot_build
host = %(host)s SET
WHERE host = %%(host)s
runbot_build.id IN (
SELECT
runbot_build.id
FROM
runbot_build
LEFT JOIN runbot_branch ON runbot_branch.id = runbot_build.branch_id
WHERE WHERE
runbot_build.repo_id IN %(repo_ids)s runbot_build.id IN (
AND runbot_build.local_state = 'pending' SELECT runbot_build.id
AND runbot_build.host IS NULL FROM runbot_build
ORDER BY LEFT JOIN runbot_branch
runbot_branch.sticky DESC, ON runbot_branch.id = runbot_build.branch_id
runbot_branch.priority DESC, WHERE
array_position(array['normal','rebuild','indirect','scheduled']::varchar[], runbot_build.build_type) ASC, runbot_build.repo_id IN %%(repo_ids)s
runbot_build.sequence ASC AND runbot_build.local_state = 'pending'
FOR UPDATE OF runbot_build SKIP LOCKED AND runbot_build.host IS NULL
LIMIT %(assignable_slots)s)""" %s
ORDER BY
array_position(array['normal','rebuild','indirect','scheduled']::varchar[], runbot_build.build_type) ASC,
runbot_branch.sticky DESC,
runbot_branch.priority DESC,
runbot_build.sequence ASC
FOR UPDATE OF runbot_build SKIP LOCKED
LIMIT %%(limit)s
)
RETURNING id""" % where_clause
self.env.cr.execute(query, {'repo_ids': tuple(ids), 'host': fqdn(), 'limit': limit})
return self.env.cr.fetchall()
allocated = allocate_builds("""AND runbot_build.build_type != 'scheduled'""", assignable_slots)
_logger.debug('Normal builds %s where allocated to runbot' % allocated)
weak_slot = assignable_slots - len(allocated) - 1
if weak_slot > 0:
allocated = allocate_builds('', weak_slot)
_logger.debug('Scheduled builds %s where allocated to runbot' % allocated)
self.env.cr.execute(query, {'repo_ids': tuple(ids), 'host': fqdn(), 'assignable_slots': assignable_slots})
pending_build = Build.search(domain_host + [('local_state', '=', 'pending')], limit=available_slots) pending_build = Build.search(domain_host + [('local_state', '=', 'pending')], limit=available_slots)
if pending_build: if pending_build:
pending_build._schedule() pending_build._schedule()