This is not a feature request per se, but it is not exactly a bug report 
either.

 

We are recently upgrading from Django 1.5 to Django 1.6.7. One other 
relevant package version of interest is psycopg2 which is at 2.5.4.

 

After upgrade, many test cases were failing with the classic 
"InterfaceError: connection already closed" originating from psycopg2. Here 
is a typical stack trace in which user-name and app-name have been obscured.

 

 

  File "/home/user1/sme-appname/src/session_csrf/__init__.py", line 68, in 
process_view

    token = cache.get(PREFIX + key, '')

  File 
"/home/user1/sme-appname/lib/python2.7/site-packages/django/core/cache/backends/db.py",
 
line 61, in get

    cursor = connections[db].cursor()

  File 
"/home/user1/sme-appname/lib/python2.7/site-packages/django/db/backends/__init__.py",
 
line 162, in cursor

    cursor = util.CursorWrapper(self._cursor(), self)

  File 
"/home/user1/sme-appname/lib/python2.7/site-packages/django/db/backends/__init__.py",
 
line 134, in _cursor

    return self.create_cursor()

  File 
"/home/user1/sme-appname/lib/python2.7/site-packages/django/db/utils.py", 
line 99, in __exit__

    six.reraise(dj_exc_type, dj_exc_value, traceback)

  File 
"/home/user1/sme-appname/lib/python2.7/site-packages/django/db/backends/__init__.py",
 
line 134, in _cursor

    return self.create_cursor()

  File 
"/home/user1/sme-appname/lib/python2.7/site-packages/django/db/backends/postgresql_psycopg2/base.py",
 
line 138, in create_cursor

    cursor = self.connection.cursor()

InterfaceError: connection already closed

 

I posted this on psycopg2 mailing list, but was told to contact you Django 
guys. Anyway, after tinkering around with some code in the django/db 
directory, I generated the following "fix" that helped most of our test 
cases to pass. The fix is in two files:

 

(1) django/db/backends/__init__.py   --> comment out the code that compares 
two autocommit values.

 

    def close_if_unusable_or_obsolete(self):

        """

        Closes the current connection if unrecoverable errors have occurred,

        or if it outlived its maximum age.

        """

        if self.connection is not None:

            # If the application didn't restore the original autocommit 
setting,

            # don't take chances, drop the connection.

            #if self.get_autocommit() != self.settings_dict['AUTOCOMMIT']:

            #    print("---- from within close_if_unusable_or_obsolete 
method ----")

            #    print("---- two autocommit settings not equal ----")

            #    print(self.get_autocommit())

            #    print(self.settings_dict['AUTOCOMMIT'])

            #    self.close()

            #    return

 

            if self.errors_occurred:

                if self.is_usable():

                    self.errors_occurred = False

                else:

                    print("---- from within close_if_unusable_or_obsolete 
method ----")

                    self.close()

                    return

 

            if self.close_at is not None and time.time() >= self.close_at:

                print("---- from within close_if_unusable_or_obsolete 
method ----")

                self.close()

                return

 

(2) django/db/__init__.py  --> simply call the recommended 
close_old_connections() as the comment in close_connection suggests, and 
comment out the old code.

 

 

def close_connection(**kwargs):

    #warnings.warn(

    #    "close_connection is superseded by close_old_connections.",

    #    PendingDeprecationWarning, stacklevel=2)

    ## Avoid circular imports

    #from django.db import transaction

    #for conn in connections:

    #    # If an error happens here the connection will be left in broken

    #    # state. Once a good db connection is again available, the

    #    # connection state will be cleaned up.

    #    transaction.abort(conn)

    #    print("---- from within close_connection method ----")

    #    connections[conn].close()

    close_old_connections()

 

 

I am not a Django expert, much less a Django/db expert. Could somebody 
investigate whether something like this can be done and released in Django 
1.6.8? I am especially puzzled by why the two autocommit values are 
different. Should I do something else (in Django test 
client/settings/elsewhere) to make the two autocommit values the same? If 
this "fix" helps you guys, fine; we are interested in some proper fix 
coming from Django directly rather than patching things up ourselves.

 

Thanks,

Arun

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/0a553f4e-1256-4e36-8d8d-57b78713ecf4%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to