adds notifications processing after every PQexec

This commit is contained in:
Roman Konoval 2024-09-11 16:29:22 +02:00 committed by Daniele Varrazzo
parent 362cb00978
commit 282360dd04
3 changed files with 73 additions and 6 deletions

View File

@ -1344,6 +1344,11 @@ conn_set_session(connectionObject *self, int autocommit,
} }
} }
Py_BLOCK_THREADS;
conn_notifies_process(self);
conn_notice_process(self);
Py_UNBLOCK_THREADS;
if (autocommit != SRV_STATE_UNCHANGED) { if (autocommit != SRV_STATE_UNCHANGED) {
self->autocommit = autocommit; self->autocommit = autocommit;
} }
@ -1408,6 +1413,11 @@ conn_set_client_encoding(connectionObject *self, const char *pgenc)
goto endlock; goto endlock;
} }
Py_BLOCK_THREADS;
conn_notifies_process(self);
conn_notice_process(self);
Py_UNBLOCK_THREADS;
endlock: endlock:
pthread_mutex_unlock(&self->lock); pthread_mutex_unlock(&self->lock);
Py_END_ALLOW_THREADS; Py_END_ALLOW_THREADS;

View File

@ -469,6 +469,7 @@ pq_abort(connectionObject *conn)
retvalue = pq_abort_locked(conn, &_save); retvalue = pq_abort_locked(conn, &_save);
Py_BLOCK_THREADS; Py_BLOCK_THREADS;
conn_notifies_process(conn);
conn_notice_process(conn); conn_notice_process(conn);
Py_UNBLOCK_THREADS; Py_UNBLOCK_THREADS;
@ -539,6 +540,7 @@ pq_reset(connectionObject *conn)
Py_BLOCK_THREADS; Py_BLOCK_THREADS;
conn_notice_process(conn); conn_notice_process(conn);
conn_notifies_process(conn);
Py_UNBLOCK_THREADS; Py_UNBLOCK_THREADS;
pthread_mutex_unlock(&conn->lock); pthread_mutex_unlock(&conn->lock);

View File

@ -23,13 +23,14 @@
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
# License for more details. # License for more details.
import os
import unittest import unittest
from collections import deque from collections import deque
import psycopg2 import psycopg2
from psycopg2 import extensions from psycopg2 import extensions
from psycopg2.extensions import Notify from psycopg2.extensions import Notify
from .testutils import ConnectingTestCase, skip_if_crdb, slow from .testutils import ConnectingTestCase, skip_if_crdb, skip_if_windows, slow
from .testconfig import dsn from .testconfig import dsn
import sys import sys
@ -74,7 +75,9 @@ conn.close()
module=psycopg2.__name__, module=psycopg2.__name__,
dsn=dsn, sec=sec, name=name, payload=payload)) dsn=dsn, sec=sec, name=name, payload=payload))
return Popen([sys.executable, '-c', script], stdout=PIPE) env = os.environ.copy()
env.pop("PSYCOPG_DEBUG", None)
return Popen([sys.executable, '-c', script], stdout=PIPE, env=env)
@slow @slow
def test_notifies_received_on_poll(self): def test_notifies_received_on_poll(self):
@ -127,16 +130,68 @@ conn.close()
self.assertEqual('foo', self.conn.notifies[0][1]) self.assertEqual('foo', self.conn.notifies[0][1])
@slow @slow
@skip_if_windows
def test_notifies_received_on_commit(self): def test_notifies_received_on_commit(self):
self.listen("foo") self.listen('foo')
self.conn.commit() self.conn.commit()
self.conn.cursor().execute("select 1;") self.conn.cursor().execute('select 1;')
pid = int(self.notify("foo").communicate()[0]) pid = int(self.notify('foo').communicate()[0])
self.assertEqual(0, len(self.conn.notifies)) self.assertEqual(0, len(self.conn.notifies))
self.conn.commit() self.conn.commit()
self.assertEqual(1, len(self.conn.notifies)) self.assertEqual(1, len(self.conn.notifies))
self.assertEqual(pid, self.conn.notifies[0][0]) self.assertEqual(pid, self.conn.notifies[0][0])
self.assertEqual("foo", self.conn.notifies[0][1]) self.assertEqual('foo', self.conn.notifies[0][1])
@slow
@skip_if_windows
def test_notifies_received_on_rollback(self):
self.listen('foo')
self.conn.commit()
self.conn.cursor().execute('select 1;')
pid = int(self.notify('foo').communicate()[0])
self.assertEqual(0, len(self.conn.notifies))
self.conn.rollback()
self.assertEqual(1, len(self.conn.notifies))
self.assertEqual(pid, self.conn.notifies[0][0])
self.assertEqual('foo', self.conn.notifies[0][1])
@slow
@skip_if_windows
def test_notifies_received_on_reset(self):
self.listen('foo')
self.conn.commit()
pid = int(self.notify('foo').communicate()[0])
self.assertEqual(0, len(self.conn.notifies))
self.conn.reset()
self.assertEqual(1, len(self.conn.notifies))
self.assertEqual(pid, self.conn.notifies[0][0])
self.assertEqual('foo', self.conn.notifies[0][1])
@slow
@skip_if_windows
def test_notifies_received_on_set_session(self):
self.listen('foo')
self.conn.commit()
pid = int(self.notify('foo').communicate()[0])
self.assertEqual(0, len(self.conn.notifies))
self.conn.set_session(autocommit=True, readonly=True)
self.assertEqual(1, len(self.conn.notifies))
self.assertEqual(pid, self.conn.notifies[0][0])
self.assertEqual('foo', self.conn.notifies[0][1])
@slow
@skip_if_windows
def test_notifies_received_on_set_client_encoding(self):
self.listen('foo')
self.conn.commit()
pid = int(self.notify('foo').communicate()[0])
self.assertEqual(0, len(self.conn.notifies))
self.conn.set_client_encoding(
'LATIN1' if self.conn.encoding != 'LATIN1' else 'UTF8'
)
self.assertEqual(1, len(self.conn.notifies))
self.assertEqual(pid, self.conn.notifies[0][0])
self.assertEqual('foo', self.conn.notifies[0][1])
@slow @slow
def test_notify_object(self): def test_notify_object(self):