Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

DataError when underlying type changes

#183

Submitted by: Chad Whitacre (whit537)

psycopg2 caches the attributes of composite types, so that when the type is altered in the database, the next attempt to cast that type in psycopg2 results in a DataError. This seems to introduce a race condition between modifying the database and restarting processes accessing the database.

More information:

https://github.com/gittip/www.gittip.com/issues/1583

Reported by Psycopg website · October 11th, 2013 @ 06:48 PM

State: invalid
Milestone: none
Assigned to: nobody

Activity

  1. Daniele Varrazzo
    Daniele Varrazzo
    • State changed from new to invalid

    Caching of the attribute is necessary but it's local to the scope you have registered the composite.

    Avoid using register_composite with global=True: use it on the connection or on the cursor, and dispose the connection or the cursor after the data type is changed. Alternatively just call register_composite again.

    October 11th, 2013 @ 10:41 PM

  2. Chad Whitacre
    Chad Whitacre

    Thanks @dvarrazzo. Scoping our register_composite calls to the connection or cursor would narrow the race condition, but wouldn't eliminate it. I'm not sure we can eliminate it, though, so what would you think of raising a subclass of DataError in CompositeCaster.parse instead of DataError itself? That way our application could catch that (without swallowing other, unrelated DataErrors) and then retry register_composite or take other measures. Would this be acceptable to you?

    October 12th, 2013 @ 02:13 AM

  3. Daniele Varrazzo
    Daniele Varrazzo

    Hello Chad,

    the use case for such subclass is fairly restricted, and I think it would be more the hassle to document it than its general usefulness, not to mention that people is usually unhappy to get a new feature in rel. 2.5.2.

    So my suggestion is you make your own subclass of the adapter, which should be something as easy as (untested):

    class CompositeChanged(DataError):
        pass
    
    class OurCompositeCaster(CompositeCaster):
        def parse(self, s, curs):
            try:
                return super(OurCompositeCaster, self).parse(s, curs)
            except DataError, e:
                raise CompositeChanged(str(e))
    

    this should do everything you need.

    October 14th, 2013 @ 11:15 AM

  4. Chad Whitacre
    Chad Whitacre

    Sounds sensible. Thanks Daniele! :-)

    October 14th, 2013 @ 09:04 PM