В моем веб-приложении некоторые sql-запросы postgres берут время для выполнения. Я хочу установить тайм-аут инструкции только для части.
Одна часть запросов должна быть отменена таймаутом, но другая должна работать без каких-либо ограничений.
В postgres существует функция statement_timeout.
Как перенести запрос SqlAlchemy с помощью функции statement_timeout?
Вот так:
SET statement_timeout TO 1000; -- timeout for one second
<sqlalchemy generated query>;
RESET statement_timeout; -- reset
Отличный способ для меня установить таймаут для запроса следующим образом:
users = session.query(User).timeout(0.5).all()
SqlAlchemy должен: 1) установить тайм-аут оператора 2) выполнить запрос и вернуть результат 3) reset тайм-аут оператора для текущего сеанса
Может быть другим способом задать тайм-аут для выполнения запроса?
ОБНОВЛЕНИЕ 1. Мое решение
Мое решение - настраиваемый прокси-сервер (протестирован с psycopg2 == 2.4 и SQLAlchemy == 0.6.6):
from sqlalchemy.interfaces import ConnectionProxy
class TimeOutProxy(ConnectionProxy):
def cursor_execute(self, execute, cursor, statement, parameters, context, executemany):
timeout = context.execution_options.get('timeout', None)
if timeout:
c = cursor._parent.cursor()
c.execute('SET statement_timeout TO %d;' % int(timeout * 1000))
c.close()
return execute(cursor, statement, parameters, context)
engine = create_engine(URL, proxy=TimeOutProxy(), pool_size=1, max_overflow=0)
Это решение без реестрирования statement_timeout, поскольку каждый запрос SqlAlchemy выполняется в изолированной транзакции и statement_timeout, определенный внутри текущей транзакции.
Пример использования (время ожидания в секундах):
Session.query(Author).execution_options(timeout=0.001).all()
Session.bind.execute(text('select * from author;') \
.execution_options(timeout=0.001)) \
.fetchall()