[API][ADMIN_API] Fix small race in SQLAlchemy + galera
It is possible for a session to be cleared before galera replication is done causing a transaction abort. Now only switch engines for sessions after 60 seconds of idle time. This also gives us a 60 second failover window. Change-Id: I8db17a13f460d4be580a170d8cfdcbab40eb6b02
This commit is contained in:
@@ -18,6 +18,7 @@ from sqlalchemy.ext.declarative import declarative_base
|
|||||||
from sqlalchemy.orm import relationship, backref, sessionmaker, Session
|
from sqlalchemy.orm import relationship, backref, sessionmaker, Session
|
||||||
import sqlalchemy.types as types
|
import sqlalchemy.types as types
|
||||||
import random
|
import random
|
||||||
|
import time
|
||||||
import ConfigParser
|
import ConfigParser
|
||||||
from pecan import conf
|
from pecan import conf
|
||||||
|
|
||||||
@@ -140,17 +141,22 @@ class Node(DeclarativeBase):
|
|||||||
|
|
||||||
class RoutingSession(Session):
|
class RoutingSession(Session):
|
||||||
""" If an engine is already in use, re-use it. Otherwise we can end up
|
""" If an engine is already in use, re-use it. Otherwise we can end up
|
||||||
with deadlocks in Galera, see http://tinyurl.com/9h6qlly """
|
with deadlocks in Galera, see http://tinyurl.com/9h6qlly
|
||||||
|
switch engines every 60 seconds of idle time """
|
||||||
|
|
||||||
last_engine = None
|
last_engine = None
|
||||||
|
last_engine_time = 0
|
||||||
|
|
||||||
def get_bind(self, mapper=None, clause=None):
|
def get_bind(self, mapper=None, clause=None):
|
||||||
if (
|
if (
|
||||||
RoutingSession.last_engine
|
RoutingSession.last_engine
|
||||||
and RoutingSession.last_engine.pool.checkedout() > 0
|
and time.time() < RoutingSession.last_engine_time + 60
|
||||||
):
|
):
|
||||||
|
RoutingSession.last_engine_time = time.time()
|
||||||
return RoutingSession.last_engine
|
return RoutingSession.last_engine
|
||||||
engine = random.choice(engines)
|
engine = random.choice(engines)
|
||||||
RoutingSession.last_engine = engine
|
RoutingSession.last_engine = engine
|
||||||
|
RoutingSession.last_engine_time = time.time()
|
||||||
return engine
|
return engine
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ from sqlalchemy import INTEGER, VARCHAR, BIGINT
|
|||||||
from sqlalchemy.ext.declarative import declarative_base
|
from sqlalchemy.ext.declarative import declarative_base
|
||||||
from sqlalchemy.orm import relationship, backref, sessionmaker, Session
|
from sqlalchemy.orm import relationship, backref, sessionmaker, Session
|
||||||
import sqlalchemy.types as types
|
import sqlalchemy.types as types
|
||||||
|
import time
|
||||||
import random
|
import random
|
||||||
import ConfigParser
|
import ConfigParser
|
||||||
from pecan import conf
|
from pecan import conf
|
||||||
@@ -140,17 +141,22 @@ class Node(DeclarativeBase):
|
|||||||
|
|
||||||
class RoutingSession(Session):
|
class RoutingSession(Session):
|
||||||
""" If an engine is already in use, re-use it. Otherwise we can end up
|
""" If an engine is already in use, re-use it. Otherwise we can end up
|
||||||
with deadlocks in Galera, see http://tinyurl.com/9h6qlly """
|
with deadlocks in Galera, see http://tinyurl.com/9h6qlly
|
||||||
|
switch engines every 60 seconds of idle time """
|
||||||
|
|
||||||
last_engine = None
|
last_engine = None
|
||||||
|
last_engine_time = 0
|
||||||
|
|
||||||
def get_bind(self, mapper=None, clause=None):
|
def get_bind(self, mapper=None, clause=None):
|
||||||
if (
|
if (
|
||||||
RoutingSession.last_engine
|
RoutingSession.last_engine
|
||||||
and RoutingSession.last_engine.pool.checkedout() > 0
|
and time.time() < RoutingSession.last_engine_time + 60
|
||||||
):
|
):
|
||||||
|
RoutingSession.last_engine_time = time.time()
|
||||||
return RoutingSession.last_engine
|
return RoutingSession.last_engine
|
||||||
engine = random.choice(engines)
|
engine = random.choice(engines)
|
||||||
RoutingSession.last_engine = engine
|
RoutingSession.last_engine = engine
|
||||||
|
RoutingSession.last_engine_time = time.time()
|
||||||
return engine
|
return engine
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user