wulczer/txpostgres

psycopg2.OperationalError: SSL connection has been closed unexpectedly

Closed this issue · 3 comments

I have modified your reconnect example (basically removed the reconnection part).

When restarting the database psycopg2.OperationalError is not handled.

http://pastebin.com/y5xgVB0a

Hi!

I believe what happens is that the errback you're attaching in runLoopingQuery is the one stopping the reactor. If you use the error function you also have defined (but are not using) the script does not exit after a database restart.

Having a traceback printed to the console in situations like this is, I'm afraid, unevitable. The deferred returned from connect() has already fired and there's no way txpostgres can notify user code about an error when reading from the socket. I think it's better to raise that error and let Twisted handle it (by printing a traceback to the log) than silently swallow it. Bear in mind that the deferred returned from runQuery() has its errback called correctly and user code can handle it however it likes.

If you really want to handle all errors yourself, you can subclass txpostgres.Connection and add a try/catch in doRead that will implement your logic.

Here's the change I made to your script:

--- /tmp/orig.py   2014-02-28 10:18:44.207284413 +0100
+++ /tmp/changed.py  2014-02-28 10:18:56.767393447 +0100
@@ -18,7 +18,7 @@

 def runLoopingQuery(conn):
     d = conn.runQuery('select 1')
-    d.addCallbacks(result, connectionError)
+    d.addCallbacks(result, error)

 def connected(_, conn):
     print '-> connected, running a query periodically'

with that, the output is:

-> connected, running a query periodically
-> query returned result: [(1,)]
-> query returned result: [(1,)]
Unhandled Error
Traceback (most recent call last):
  File "/venv/local/lib/python2.7/site-packages/twisted/python/log.py", line 84, in callWithLogger
    return callWithContext({"system": lp}, func, *args, **kw)
  File "/venv/local/lib/python2.7/site-packages/twisted/python/log.py", line 69, in callWithContext
    return context.call({ILogContext: newCtx}, func, *args, **kw)
  File "/venv/local/lib/python2.7/site-packages/twisted/python/context.py", line 118, in callWithContext
    return self.currentContext().callWithContext(ctx, func, *args, **kw)
  File "/venv/local/lib/python2.7/site-packages/twisted/python/context.py", line 81, in callWithContext
    return func(*args,**kw)
--- <exception caught here> ---
  File "/venv/local/lib/python2.7/site-packages/twisted/internet/posixbase.py", line 581, in _doReadOrWrite
    why = selectable.doRead()
  File "/venv/local/lib/python2.7/site-packages/txpostgres/txpostgres.py", line 675, in doRead
    _PollingMixin.doRead(self)
  File "/venv/local/lib/python2.7/site-packages/txpostgres/txpostgres.py", line 196, in doRead
    self.continuePolling()
  File "/venv/local/lib/python2.7/site-packages/txpostgres/txpostgres.py", line 168, in continuePolling
    state = self.pollable().poll()
psycopg2.OperationalError: 
-> query failed with OperationalError('connection not open\n',)
-> query failed with OperationalError('connection not open\n',)
-> query failed with OperationalError('connection not open\n',)
-> query failed with OperationalError('connection not open\n',)
-> query failed with OperationalError('connection not open\n',)

Sorry, I didn't get notified about your response. Its been a while now, but as far as I can recover my thoughts, your answer makes sense.
(Btw.: I am using the LoggingDetector from your example successfully now).
Thanks!

Cool! I'll close the issue then.