mirror of
https://github.com/Dispatcharr/Dispatcharr.git
synced 2026-07-17 16:50:53 +00:00
Enhancement: Update psycopg2 to 3.
This commit is contained in:
parent
d6f837238f
commit
80b72d8cfa
7 changed files with 26 additions and 40 deletions
|
|
@ -1,6 +1,6 @@
|
|||
import sys
|
||||
import psycopg2
|
||||
from psycopg2 import sql
|
||||
import psycopg
|
||||
from psycopg import sql
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.conf import settings
|
||||
from django.db import connection
|
||||
|
|
@ -38,8 +38,7 @@ class Command(BaseCommand):
|
|||
maintenance_db = 'postgres'
|
||||
try:
|
||||
self.stdout.write("Connecting to maintenance database...")
|
||||
conn = psycopg2.connect(dbname=maintenance_db, user=user, password=password, host=host, port=port, **ssl_kwargs)
|
||||
conn.autocommit = True
|
||||
conn = psycopg.connect(dbname=maintenance_db, user=user, password=password, host=host, port=port, autocommit=True, **ssl_kwargs)
|
||||
cur = conn.cursor()
|
||||
self.stdout.write(f"Dropping database '{db_name}'...")
|
||||
cur.execute(sql.SQL("DROP DATABASE IF EXISTS {}").format(sql.Identifier(db_name)))
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ class EpgIgnoreListsTest(TestCase):
|
|||
|
||||
|
||||
class DropDBCommandTlsTest(TestCase):
|
||||
"""Verify dropdb management command passes TLS parameters to psycopg2."""
|
||||
"""Verify dropdb management command passes TLS parameters to psycopg."""
|
||||
databases = []
|
||||
|
||||
_DB_WITH_TLS = {
|
||||
|
|
@ -184,7 +184,7 @@ class DropDBCommandTlsTest(TestCase):
|
|||
}
|
||||
}
|
||||
|
||||
@patch('core.management.commands.dropdb.psycopg2.connect')
|
||||
@patch('core.management.commands.dropdb.psycopg.connect')
|
||||
@patch('core.management.commands.dropdb.connection')
|
||||
@patch('builtins.input', return_value='yes')
|
||||
def test_dropdb_passes_ssl_kwargs_when_tls_enabled(self, _inp, _conn, mock_connect):
|
||||
|
|
@ -199,13 +199,14 @@ class DropDBCommandTlsTest(TestCase):
|
|||
mock_connect.assert_called_once_with(
|
||||
dbname='postgres', user='testuser', password='testpass',
|
||||
host='localhost', port=5432,
|
||||
autocommit=True,
|
||||
sslmode='verify-full',
|
||||
sslrootcert='/certs/ca.crt',
|
||||
sslcert='/certs/client.crt',
|
||||
sslkey='/certs/client.key',
|
||||
)
|
||||
|
||||
@patch('core.management.commands.dropdb.psycopg2.connect')
|
||||
@patch('core.management.commands.dropdb.psycopg.connect')
|
||||
@patch('core.management.commands.dropdb.connection')
|
||||
@patch('builtins.input', return_value='yes')
|
||||
def test_dropdb_no_ssl_kwargs_when_tls_disabled(self, _inp, _conn, mock_connect):
|
||||
|
|
@ -220,4 +221,5 @@ class DropDBCommandTlsTest(TestCase):
|
|||
mock_connect.assert_called_once_with(
|
||||
dbname='postgres', user='testuser', password='testpass',
|
||||
host='localhost', port=5432,
|
||||
autocommit=True,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,24 +1,20 @@
|
|||
"""
|
||||
Loaded via uWSGI's `import = dispatcharr.gevent_patch` directive.
|
||||
|
||||
Two things happen here:
|
||||
gevent stdlib monkey-patching - replaces blocking socket/threading/os
|
||||
primitives with gevent-cooperative versions. `gevent-early-monkey-patch = true`
|
||||
in the ini should already have done this; calling it again is a safe no-op if
|
||||
it did, and a necessary fallback if it didn't (e.g. older uWSGI build).
|
||||
|
||||
1. gevent stdlib monkey-patching - replaces blocking socket/threading/os
|
||||
primitives with gevent-cooperative versions. `gevent-early-monkey-patch = true`
|
||||
in the ini should already have done this; calling it again is a safe no-op if
|
||||
it did, and a necessary fallback if it didn't (e.g. older uWSGI build).
|
||||
|
||||
2. psycogreen - installs a wait callback on psycopg2 so libpq yields to the
|
||||
gevent hub during I/O instead of blocking the OS thread.
|
||||
|
||||
Without (1), `async_to_sync(channel_layer.group_send)` in send_websocket_update
|
||||
Without this, `async_to_sync(channel_layer.group_send)` in send_websocket_update
|
||||
calls epoll_wait() directly, which blocks the OS thread and freezes all greenlets
|
||||
on the worker until the call returns. With (1), select.epoll is replaced by
|
||||
monkey-patching, which breaks asyncio event loop creation in threadpool threads.
|
||||
on the worker until the call returns. With monkey-patching, select.epoll is
|
||||
replaced, which breaks asyncio event loop creation in threadpool threads.
|
||||
send_websocket_update therefore uses a synchronous Redis path in gevent workers
|
||||
instead of asyncio - see _gevent_ws_send() in core/utils.py.
|
||||
|
||||
Without (2), psycopg2 network calls pin the worker during slow/stalled queries.
|
||||
psycopg3 uses Python's socket layer for I/O, so monkey.patch_all() provides
|
||||
gevent compatibility without any additional driver patching.
|
||||
|
||||
Celery and Daphne run in separate daemon processes and do not load this module.
|
||||
|
||||
|
|
@ -40,15 +36,4 @@ if not monkey.is_module_patched("socket"):
|
|||
else:
|
||||
print("[gevent_patch] gevent stdlib monkey-patching already active.", flush=True)
|
||||
|
||||
try:
|
||||
from psycogreen.gevent import patch_psycopg
|
||||
patch_psycopg()
|
||||
print("[gevent_patch] psycogreen: psycopg2 patched for gevent.", flush=True)
|
||||
except ImportError:
|
||||
print(
|
||||
"[gevent_patch] WARNING: psycogreen not installed - "
|
||||
"psycopg2 will block the gevent hub during DB I/O. "
|
||||
"Run: uv pip install psycogreen",
|
||||
file=sys.stderr,
|
||||
flush=True,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@ gevent = 100
|
|||
|
||||
# Patch the stdlib (socket, threading, time, ...) before any app code
|
||||
# loads so blocking calls yield to the gevent hub. Without this, a single
|
||||
# blocking psycopg2 / requests / DNS call freezes every greenlet on the
|
||||
# worker. The companion module greens psycopg2 specifically.
|
||||
# blocking requests / DNS call freezes every greenlet on the
|
||||
# worker. psycopg3 uses Python's socket layer, so no additional patching is needed.
|
||||
gevent-early-monkey-patch = true
|
||||
import = dispatcharr.gevent_patch
|
||||
|
||||
|
|
|
|||
|
|
@ -45,8 +45,8 @@ gevent = 100
|
|||
|
||||
# Patch the stdlib (socket, threading, time, ...) before any app code
|
||||
# loads so blocking calls yield to the gevent hub. Without this, a single
|
||||
# blocking psycopg2 / requests / DNS call freezes every greenlet on the
|
||||
# worker. The companion module greens psycopg2 specifically.
|
||||
# blocking requests / DNS call freezes every greenlet on the
|
||||
# worker. psycopg3 uses Python's socket layer, so no additional patching is needed.
|
||||
gevent-early-monkey-patch = true
|
||||
import = dispatcharr.gevent_patch
|
||||
|
||||
|
|
|
|||
|
|
@ -48,8 +48,8 @@ gevent = 400 # Each unused greenlet costs ~2-4KB of memory
|
|||
|
||||
# Patch the stdlib (socket, threading, time, ...) before any app code
|
||||
# loads so blocking calls yield to the gevent hub. Without this, a single
|
||||
# blocking psycopg2 / requests / DNS call freezes every greenlet on the
|
||||
# worker. The companion module greens psycopg2 specifically.
|
||||
# blocking requests / DNS call freezes every greenlet on the
|
||||
# worker. psycopg3 uses Python's socket layer, so no additional patching is needed.
|
||||
gevent-early-monkey-patch = true
|
||||
import = dispatcharr.gevent_patch
|
||||
|
||||
|
|
|
|||
|
|
@ -44,8 +44,8 @@ gevent = 400 # Each unused greenlet costs ~2-4KB of memory
|
|||
|
||||
# Patch the stdlib (socket, threading, time, ...) before any app code
|
||||
# loads so blocking calls yield to the gevent hub. Without this, a single
|
||||
# blocking psycopg2 / requests / DNS call freezes every greenlet on the
|
||||
# worker. The companion module greens psycopg2 specifically.
|
||||
# blocking requests / DNS call freezes every greenlet on the
|
||||
# worker. psycopg3 uses Python's socket layer, so no additional patching is needed.
|
||||
gevent-early-monkey-patch = true
|
||||
import = dispatcharr.gevent_patch
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue