mirror of
https://github.com/healthchecks/healthchecks.git
synced 2025-01-11 19:38:11 +00:00
Update Webhook transport to close db connection before network IO
Webhook requests can take 20+ seconds. During that time we hold on to a database connection. With this commit, the Webhook transport closes its DB connection before making a curl call. With psycopg2 this does not have much effect. But with psycopg 3 & connection pooling we will be able to use more sendalerts workers than we have database connections. While one worker is busy making a slow curl call, another worker can grab its freed up connection and do some work. Django's test runner is not happy with connections closed mid-test, so I patched out close_old_connections() in affected tests.
This commit is contained in:
parent
9803d77a1d
commit
a463daa775
3 changed files with 16 additions and 11 deletions
hc
|
@ -14,6 +14,7 @@ from hc.lib.curl import CurlError
|
|||
from hc.test import BaseTestCase
|
||||
|
||||
|
||||
@patch("hc.api.transports.close_old_connections", Mock())
|
||||
class NotifyWebhookTestCase(BaseTestCase):
|
||||
def _setup_data(
|
||||
self, value: str, status: str = "down", email_verified: bool = True
|
||||
|
|
|
@ -13,6 +13,7 @@ from typing import TYPE_CHECKING, Any, NoReturn, cast
|
|||
from urllib.parse import quote, urlencode, urljoin
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import close_old_connections
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.html import escape
|
||||
from pydantic import BaseModel, ValidationError
|
||||
|
@ -387,24 +388,26 @@ class Webhook(HttpTransport):
|
|||
if not spec.url:
|
||||
raise TransportError("Empty webhook URL")
|
||||
|
||||
method = spec.method.lower()
|
||||
url = self.prepare(spec.url, flip, urlencode=True)
|
||||
headers = {}
|
||||
for key, value in spec.headers.items():
|
||||
# Header values should contain ASCII and latin-1 only
|
||||
headers[key] = self.prepare(value, flip, latin1=True)
|
||||
|
||||
body, body_bytes = spec.body, None
|
||||
if body and spec.method in ("POST", "PUT"):
|
||||
body = self.prepare(body, flip, allow_ping_body=True)
|
||||
body_bytes = body.encode()
|
||||
|
||||
retry = True
|
||||
if notification.owner is None:
|
||||
# This is a test notification.
|
||||
# When sending a test notification, don't retry on failures.
|
||||
retry = False
|
||||
|
||||
method = spec.method.lower()
|
||||
body, body_bytes = spec.body, None
|
||||
if body and spec.method in ("POST", "PUT"):
|
||||
body = self.prepare(body, flip, allow_ping_body=True)
|
||||
body_bytes = body.encode()
|
||||
|
||||
headers = {}
|
||||
for key, value in spec.headers.items():
|
||||
# Header values should contain ASCII and latin-1 only
|
||||
headers[key] = self.prepare(value, flip, latin1=True)
|
||||
|
||||
# Give up database connection before potentially long network IO:
|
||||
close_old_connections()
|
||||
self.request(method, url, retry=retry, data=body_bytes, headers=headers)
|
||||
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ from hc.api.models import Channel, Notification
|
|||
from hc.test import BaseTestCase
|
||||
|
||||
|
||||
@patch("hc.api.transports.close_old_connections", Mock())
|
||||
class SendTestNotificationTestCase(BaseTestCase):
|
||||
def setUp(self) -> None:
|
||||
super().setUp()
|
||||
|
|
Loading…
Reference in a new issue