[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:
Andrew Hutchings
2013-07-05 16:49:01 +01:00
parent a197acd6f4
commit bf0b9c90d6
2 changed files with 16 additions and 4 deletions

View File

@@ -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

View File

@@ -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