From 2eb464087b831dcb1d2b926f9ef072da79e135f1 Mon Sep 17 00:00:00 2001 From: "James E. Blair" Date: Mon, 29 Jul 2024 13:51:20 -0700 Subject: [PATCH] Avoid DB exceptions on certain build cleanups If we cancel a build very early (before it starts) and there have been no builds started for the buildset, and the buildset wasn't already reported as started to the DB, then in that case we may log an exception when cleaning up the build after the cancelation. We always attempt to report a build end to the DB, but in this case we don't have any existing DB records, which means we first need to create a buildset entry in the DB. But we don't have enough information to do that properly, so we throw an exception. This exception is caught and logged, but it's not a completely unexpected situation. To avoid logging the spurious exception, indicate to the lower levels that it's okay if we don't have a buildset and we should just return without any further DB work. Change-Id: I1d600255e0218e2a6c73d134be23da665f250165 --- zuul/driver/sql/sqlreporter.py | 7 ++++++- zuul/scheduler.py | 17 +++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/zuul/driver/sql/sqlreporter.py b/zuul/driver/sql/sqlreporter.py index d225fd794a..4b70e4eb64 100644 --- a/zuul/driver/sql/sqlreporter.py +++ b/zuul/driver/sql/sqlreporter.py @@ -147,13 +147,18 @@ class SQLReporter(BaseReporter): else: self.log.exception("Unable to create build") - def reportBuildEnd(self, build, tenant, final): + def reportBuildEnd(self, build, tenant, final, + missing_buildset_okay=False): for retry_count in range(self.retry_count): try: with self.connection.getSession() as db: db_build = db.getBuild(tenant=tenant, uuid=build.uuid) if not db_build: db_build = self._createBuild(db, build) + if not db_build: + if missing_buildset_okay: + return + raise Exception("Unable to create build in DB") end_time = build.end_time or time.time() end = datetime.datetime.fromtimestamp( diff --git a/zuul/scheduler.py b/zuul/scheduler.py index 7b18d9e78f..6fc6cad676 100644 --- a/zuul/scheduler.py +++ b/zuul/scheduler.py @@ -2947,13 +2947,22 @@ class Scheduler(threading.Thread): ) self._cleanupCompletedBuild(build) - # This usually happens when we have already canceled a - # build and reported stats for it, so don't send stats in - # this case. + # If we have not reported start for this build, we don't + # need to report end. If we haven't reported start, we + # won't have a build record in the DB, so we would + # normally create one and attach it to a buildset, but we + # don't know the buildset, and we don't have enough + # information to construct a buildset record from scratch. + # Indicate that is acceptable in this situation, so we + # don't throw an exception. In other words: if we don't + # have a build record in the DB here, the + # "missing_buildset_okay" flag will cause reportBuildEnd + # to do nothing. try: self.sql.reportBuildEnd( build, tenant=pipeline.tenant.name, - final=True) + final=True, + missing_buildset_okay=True) except Exception: log.exception("Error reporting build completion to DB:")