determine "is_disconnect()" state on exception object for failed connection attempt ?

Issue #2201 resolved
Former user created an issue

Hi!

We use Session = scoped_session(sessionmaker(autocommit = False))'s execute() method to work with a database. It implicitly performs connection to desired database. If connection failes like this:

  File "query.py", line 37, in callslist_exists
    res = Session.execute(query).first()
  File "/usr/lib/python2.6/site-packages/SQLAlchemy-0.6.3-py2.6-linux-i686.egg/sqlalchemy/orm/scoping.py", line 129, in do
    return getattr(self.registry(), name)(*args, **kwargs)
  File "/usr/lib/python2.6/site-packages/SQLAlchemy-0.6.3-py2.6-linux-i686.egg/sqlalchemy/orm/session.py", line 734, in execute
    return self._connection_for_bind(engine, close_with_result=True).execute(
  File "/usr/lib/python2.6/site-packages/SQLAlchemy-0.6.3-py2.6-linux-i686.egg/sqlalchemy/orm/session.py", line 699, in _connection_for_bind
    return self.transaction._connection_for_bind(engine)
  File "/usr/lib/python2.6/site-packages/SQLAlchemy-0.6.3-py2.6-linux-i686.egg/sqlalchemy/orm/session.py", line 315, in _connection_for_bind
    conn = bind.contextual_connect()
  File "/usr/lib/python2.6/site-packages/SQLAlchemy-0.6.3-py2.6-linux-i686.egg/sqlalchemy/engine/base.py", line 1742, in contextual_connect
    self.pool.connect(),
  File "/usr/lib/python2.6/site-packages/SQLAlchemy-0.6.3-py2.6-linux-i686.egg/sqlalchemy/pool.py", line 158, in connect
    return _ConnectionFairy(self).checkout()
  File "/usr/lib/python2.6/site-packages/SQLAlchemy-0.6.3-py2.6-linux-i686.egg/sqlalchemy/pool.py", line 329, in __init__
    rec = self._connection_record = pool.get()
  File "/usr/lib/python2.6/site-packages/SQLAlchemy-0.6.3-py2.6-linux-i686.egg/sqlalchemy/pool.py", line 177, in get
    return self.do_get()
  File "/usr/lib/python2.6/site-packages/SQLAlchemy-0.6.3-py2.6-linux-i686.egg/sqlalchemy/pool.py", line 692, in do_get
    con = self.create_connection()
  File "/usr/lib/python2.6/site-packages/SQLAlchemy-0.6.3-py2.6-linux-i686.egg/sqlalchemy/pool.py", line 138, in create_connection
    return _ConnectionRecord(self)
  File "/usr/lib/python2.6/site-packages/SQLAlchemy-0.6.3-py2.6-linux-i686.egg/sqlalchemy/pool.py", line 213, in __init__
    self.connection = self.__connect()
  File "/usr/lib/python2.6/site-packages/SQLAlchemy-0.6.3-py2.6-linux-i686.egg/sqlalchemy/pool.py", line 279, in __connect
    connection = self.__pool._creator()
  File "/usr/lib/python2.6/site-packages/SQLAlchemy-0.6.3-py2.6-linux-i686.egg/sqlalchemy/engine/strategies.py", line 76, in connect
    return dialect.connect(*cargs, **cparams)
  File "/usr/lib/python2.6/site-packages/SQLAlchemy-0.6.3-py2.6-linux-i686.egg/sqlalchemy/engine/default.py", line 238, in connect
    return self.dbapi.connect(*cargs, **cparams)
OperationalError: (OperationalError) ORA-01033: ORACLE initialization or shutdown in progress

and I check exc.connection_invalidated - I get False. Don't know the reason, why it isn't set here, but I don't see other ways to check connection state correctly.

Comments (8)

  1. Mike Bayer repo owner

    oh...well the "connection invalidated" means, we had a connection, and it got invalidated. this seems like a different thing since there never was a connection.

    it doesn't seem like it should be set unconditionally - i.e. if you just supplied the wrong password, you wouldn't have a connection either. it seems like the suggestion is to run DBAPI errors through is_disconnect() even if the connection didn't occur in the first place. Kind of a new feature.

  2. Former user Account Deleted

    Oh... 0.7.2 :( Seems like I can manually recreate planning behavior manually checking is_disconnect()?

  3. Mike Bayer repo owner

    Replying to guest:

    Oh... 0.7.2 :( Seems like I can manually recreate planning behavior manually checking is_disconnect()?

    well yes, but then also we'd need to add ORA-01033 to the list that we just enhanced in #2200.

    don't worry it can probably go in 0.6.9 too but this requires some new tinkering in the mechanics, also testing to ensure that none of the dialects choke in the is_disconnect() call. Also a little disturbing that this doesn't work if you were to pass a custom connect function to create_engine(), it appears we don't wrap the exception at all though.

  4. Former user Account Deleted

    While experimenting with failed connection got another error code

    (DatabaseError) ORA-12541: TNS:no listener
    
  5. Mike Bayer repo owner

    e936a7b359a205e0476b932a1f175f5da7289e06 . This is a significant feature and behavioral change, would you mind upgrading to 0.7 or implementing a workaround if you're stuck on 0.6 for now ? if you have exception catching code that looks at the flag, then tries a re-do, just also check for ORA-01033.

    ORA-12541 is more controversial. Suppose you put the wrong host in ?

    Generally its very tough to classify an error that occurs on first connect as a "retryable" condition. Only if you've connected to that host already, and the connection drops, can you really be sure that a change on the previously correct DB host is the cause of the error.

    ORA-01033 is actually kind of special here - it means you did actually connect to a TNS listener successfully, just that the DB wasn't available.

  6. Former user Account Deleted

    Thanks for the fix!

    ORA-12541: I don't quite remember circumstances already.

    implementing a workaround if you're stuck on 0.6 for now

    Yes, I already patched my code to manually check if we need to retry connection. :)

  7. Log in to comment