psycopg版本:
3.2.3
postgres 版本:
PostgreSQL 14.13 (Homebrew) on x86_64-apple-darwin23.6.0, compiled by Apple clang version 16.0.0 (clang-1600.0.26.4), 64-bit
我有一个长时间运行的进程(可能需要几个月),它使用
conn.notifies()
监听数据库连接上的通知(请参阅 psycopg3 文档)。该文档没有指定侦听连接无响应/损坏时的预期行为,因此我相信我需要自己执行运行状况检查。
如果
conn.notifies()
保证在连接出现问题时引发异常,那么其余的就没有意义了。有谁知道吗
假设
conn.notifies()
不一定引发异常,这个github评论说我可以在监听连接上执行语句而不会丢失通知。
如果您需要在该连接上发出新的 LISTEN,您可以停止通知生成器(使用generators.close(),参见文档),执行该语句,然后再次调用notify()。这样做不会丢失消息:无论如何它们都会在 libpq 连接中缓冲。
def _listen_for_notifications():
with psycopg.Connection.connect("some_connection_string", autocommit=True) as conn:
listen_sql = sql.SQL("LISTEN {}").format(sql.Identifier("some_channel_name"))
conn.execute(listen_sql)
gen = conn.notifies(timeout=5)
print('listening')
# This prints notifications sent within the five second timeout
for n in gen:
print(n)
gen.close() # I see the same behavior with and without this line.
print("Performing health check")
# Any notifications sent over these three seconds are lost
conn.execute("select pg_sleep(3)") # Would be SELECT 1 in real code
conn.execute(listen_sql)
gen = conn.notifies(timeout=5)
print('listening again on the same connection')
# This prints notifications sent within the five second timeout
for n in gen:
print(n)
print('done!')
_listen_for_notifications()
当我在前 5 秒内发送负载为“1”的通知、在 pg_sleep(3) 执行的 3 秒期间发送负载为“2”的通知以及在最后 5 秒期间发送负载为“3”的通知时的输出。
listening
Notify(channel='some_channel_name', payload='1', pid=35237)
Performing health check
listening again on the same connection
Notify(channel='some_channel_name', payload='3', pid=35237)
done!
通知 2 丢失。
Github问题:https://github.com/psycopg/psycopg/issues/962
公关/决议:https://github.com/psycopg/psycopg/pull/975
谢谢丹尼尔瓦拉佐!