[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
|
||||
import sqlalchemy.types as types
|
||||
import random
|
||||
import time
|
||||
import ConfigParser
|
||||
from pecan import conf
|
||||
|
||||
@@ -140,17 +141,22 @@ class Node(DeclarativeBase):
|
||||
|
||||
class RoutingSession(Session):
|
||||
""" 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_time = 0
|
||||
|
||||
def get_bind(self, mapper=None, clause=None):
|
||||
if (
|
||||
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
|
||||
engine = random.choice(engines)
|
||||
RoutingSession.last_engine = engine
|
||||
RoutingSession.last_engine_time = time.time()
|
||||
return engine
|
||||
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ from sqlalchemy import INTEGER, VARCHAR, BIGINT
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy.orm import relationship, backref, sessionmaker, Session
|
||||
import sqlalchemy.types as types
|
||||
import time
|
||||
import random
|
||||
import ConfigParser
|
||||
from pecan import conf
|
||||
@@ -140,17 +141,22 @@ class Node(DeclarativeBase):
|
||||
|
||||
class RoutingSession(Session):
|
||||
""" 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_time = 0
|
||||
|
||||
def get_bind(self, mapper=None, clause=None):
|
||||
if (
|
||||
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
|
||||
engine = random.choice(engines)
|
||||
RoutingSession.last_engine = engine
|
||||
RoutingSession.last_engine_time = time.time()
|
||||
return engine
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user