![](/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.