![](/img/trans.png)
[英]sqlalchemy and asyncpg – set postgres statement_timeout
[英]How to test postgres statement_timeout in django
我在我的 Django 服务中为 postgres 数据库添加了连接和语句超时。 所以相关的 django 设置看起来像;
_CONN_TIMEOUT = 5
_STATEMENT_TIMEOUT = 3000 # millisecond
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": "some_database",
# ...,
"OPTIONS": {
"connect_timeout": _CONN_TIMEOUT,
"options": "-c statement_timeout={0}ms".format(_STATEMENT_TIMEOUT),
},
}
}
然后,我正在编写这样的测试;
class DbTimeoutTest(TestCase):
def test_db_statement_timeout(self):
"""
test carrying out an SQL query that takes longer than the configured
postgres `statement_timeout` value
"""
# set statement_timeout to 1 millisecond
mock_s_timeout = 1
with self.settings(_CONN_TIMEOUT=5, _STATEMENT_TIMEOUT=mock_s_timeout):
self.assertEqual(
settings.DATABASES["default"]["OPTIONS"]["options"],
"-c statement_timeout={0}ms".format(mock_s_timeout),
)
Book.objects.create(name="Hello")
但是,该测试不起作用。
self.assertEqual
没有通过,这意味着设置覆盖不起作用。Book.objects.create
语句因超时而失败,但事实并非如此。所以问题;
看一下 django 项目的测试用例
他们将超时设置为 1ms 并assertRaises(OperationalError)
完整代码:
def test_statement_timeout(self):
databases = copy.deepcopy(settings.DATABASES)
# Set timeout to 1ms and execute a 1s query.
databases[DEFAULT_DB_ALIAS]['STATEMENT_TIMEOUT'] = 1
new_connections = ConnectionHandler(databases)
new_connection = new_connections[DEFAULT_DB_ALIAS]
try:
with new_connection.cursor() as cursor:
with self.assertRaises(OperationalError):
cursor.execute("SELECT pg_sleep(1)")
finally:
new_connection.close()
这就是我最终要做的;
在您的settings.py
文件中:
CONNECTION_TIMEOUT = 5 # seconds
STATEMENT_TIMEOUT = 3000 # milliseconds
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": "some_database",
# ...,
"OPTIONS": {
"connect_timeout": CONNECTION_TIMEOUT,
"options": "-c statement_timeout={0}ms".format(STATEMENT_TIMEOUT),
},
}
}
在您的test_database.py
文件中:
from django.conf import settings
from django.test import TestCase
from django.db import connection
from django.db.utils import OperationalError
class DatabaseTest(TestCase):
def test_timeout(self):
statement_timeout_seconds = settings.STATEMENT_TIMEOUT / 1000
cursor = connection.cursor()
with self.assertRaises(OperationalError) as raised_exception:
cursor.execute(
# sql query that takes 3 times longer than the configured statement_timeout
"SELECT pg_sleep({0})".format((statement_timeout_seconds) * 3)
)
cursor.fetchall()
cursor.close()
self.assertIn(
"canceling statement due to statement timeout", str(raised_exception.exception)
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.