From fb972acf990ce1289ae7cb08abdc475b73df2158 Mon Sep 17 00:00:00 2001 From: Julien Danjou Date: Wed, 18 May 2016 15:06:21 +0200 Subject: [PATCH] sqlalchemy: retry on deadlock for create_resource_type() sqlalchemy.exc.InternalError: (psycopg2.InternalError) current transaction is aborted, commands ignored until end of transaction block [SQL: 'select relname from pg_class c join pg_namespace n on n.oid=c.relnamespace where pg_catalog.pg_table_is_visible(c.oid) and relname=%(name)s'] [parameters: {'name': u'rt_c5a9affa3ef94951823f3d81d50932de'}] Change-Id: Id77565677fddfc1d9b9edc074b8b808cfa23a1bd --- gnocchi/indexer/sqlalchemy.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/gnocchi/indexer/sqlalchemy.py b/gnocchi/indexer/sqlalchemy.py index 0bef78008..2968c643d 100644 --- a/gnocchi/indexer/sqlalchemy.py +++ b/gnocchi/indexer/sqlalchemy.py @@ -254,6 +254,20 @@ class SQLAlchemyIndexer(indexer.IndexerDriver): self._RESOURCE_TYPE_MANAGER.map_and_create_tables( rt, connection) + # NOTE(jd) We can have deadlock errors either here or later in + # map_and_create_tables(). We can't decorate create_resource_type() + # directly or each part might retry later on its own and cause a + # duplicate. And it seems there's no way to use the same session for + # both adding the resource_type in our table and calling + # map_and_create_tables() :-( + @retry_on_deadlock + def _add_resource_type(self, resource_type): + try: + with self.facade.writer() as session: + session.add(resource_type) + except exception.DBDuplicateEntry: + raise indexer.ResourceTypeAlreadyExists(resource_type.name) + def create_resource_type(self, resource_type): # NOTE(sileht): mysql have a stupid and small length limitation on the # foreign key and index name, so we can't use the resource type name as @@ -269,11 +283,7 @@ class SQLAlchemyIndexer(indexer.IndexerDriver): # resource_type resource_type.to_baseclass() - try: - with self.facade.writer() as session: - session.add(resource_type) - except exception.DBDuplicateEntry: - raise indexer.ResourceTypeAlreadyExists(resource_type.name) + self._add_resource_type(resource_type) with self.facade.writer_connection() as connection: self._RESOURCE_TYPE_MANAGER.map_and_create_tables(resource_type,