From 2b8a9dd5739cc8ca725a4efc15003d467267ec04 Mon Sep 17 00:00:00 2001 From: Mike McLean Date: Dec 05 2018 03:53:58 +0000 Subject: PR#1175: kojira: avoid race condition that causes "unknown task" errors Merges #1175 https://pagure.io/koji/pull-request/1175 Fixes: #942 https://pagure.io/koji/issue/942 kojira: Needed tag refers to unknown task --- diff --git a/util/kojira b/util/kojira index d9543ac..8e68cfd 100755 --- a/util/kojira +++ b/util/kojira @@ -201,6 +201,7 @@ class RepoManager(object): self._local.session = session self.repos = {} self.tasks = {} + self.recent_tasks = {} self.other_tasks = {} self.needed_tags = {} self.tag_use_stats = {} @@ -533,6 +534,13 @@ class RepoManager(object): - check for other newRepo tasks (not generated by us) """ + # prune recent tasks + now = time.time() + for task_id in list(self.recent_tasks): + if now - self.recent_tasks[task_id] > self.options.recent_tasks_lifetime: + del self.recent_tasks[task_id] + + # check on current tasks task_ids = list(self.tasks) self.session.multicall = True for task_id in task_ids: @@ -542,9 +550,11 @@ class RepoManager(object): tag_id = self.tasks[task_id]['tag_id'] if tstate == 'CLOSED': self.logger.info("Finished: newRepo task %s for tag %s" % (task_id, tag_id)) + self.recent_tasks[task_id] = time.time() del self.tasks[task_id] elif tstate in ('CANCELED', 'FAILED'): self.logger.info("Problem: newRepo task %s for tag %s is %s" % (task_id, tag_id, tstate)) + self.recent_tasks[task_id] = time.time() del self.tasks[task_id] else: self.tasks[task_id]['taskinfo'] = tinfo @@ -676,10 +686,14 @@ class RepoManager(object): if task_id in self.tasks: # we already have a task continue + elif task_id in self.recent_tasks: + # avoiding a race, see https://pagure.io/koji/issue/942 + continue else: # should not happen logger.warning('Needed tag refers to unknown task. ' '%s -> %i', tagname, task_id) + # we'll advance and create a new task taskopts = {} if koji.util.multi_fnmatch(tagname, debuginfo_pat): taskopts['debuginfo'] = True @@ -848,6 +862,7 @@ def get_options(): 'deleted_repo_lifetime': 7*24*3600, #XXX should really be called expired_repo_lifetime 'dist_repo_lifetime': 7*24*3600, + 'recent_tasks_lifetime': 600, 'sleeptime' : 15, 'cert': None, 'ca': '', # FIXME: unused, remove in next major release @@ -857,7 +872,8 @@ def get_options(): int_opts = ('deleted_repo_lifetime', 'max_repo_tasks', 'repo_tasks_limit', 'retry_interval', 'max_retries', 'offline_retry_interval', 'max_delete_processes', 'max_repo_tasks_maven', - 'delete_batch_size', 'dist_repo_lifetime', 'sleeptime') + 'delete_batch_size', 'dist_repo_lifetime', 'sleeptime', + 'recent_tasks_lifetime') str_opts = ('topdir', 'server', 'user', 'password', 'logfile', 'principal', 'keytab', 'krbservice', 'cert', 'ca', 'serverca', 'debuginfo_tags', 'source_tags', 'ignore_tags') # FIXME: remove ca here