[英]How to test postgres statement_timeout in django
I have added both connect and statement timeouts for a postgres database in my django service.我在我的 Django 服务中为 postgres 数据库添加了连接和语句超时。 So the relevant django setting looks like;
所以相关的 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),
},
}
}
And then, I'm writing tests like this;然后,我正在编写这样的测试;
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")
However, that test is not working.但是,该测试不起作用。
self.assertEqual
does not pass, meaning that the setting override did not work. self.assertEqual
没有通过,这意味着设置覆盖不起作用。Book.objects.create
statement to fail with timeout but it does not.Book.objects.create
语句因超时而失败,但事实并非如此。 So questions;所以问题;
Have a look the at django project's test case看一下 django 项目的测试用例
They set the timeout to 1ms and assertRaises(OperationalError)
他们将超时设置为 1ms 并
assertRaises(OperationalError)
Full code:完整代码:
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()
This is what I ended up doing;这就是我最终要做的;
In your settings.py
file:在您的
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),
},
}
}
And in your test_database.py
file:在您的
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.