Python + Twisted + sqlanydb = abort()

半世苍凉 提交于 2019-12-06 06:13:02

It looks like your database library is not threadsafe. In order to make it a stable connection, do this:

self.dbpool = ConnectionPool(..., cp_min=1, cp_max=1)

This will set the maximum concurrency to 1, and the ThreadPool will be limited to 1 thread, meaning that no queries will run simultaneously. This should stop your non-threadsafe library from causing you any drama, while still running the queries in a thread and not blocking the mainloop.

Yeah, your deferred list looks like it's not going to do what you want. Each runQuery is going to be run in a adbapi threadpool so there's no guarantee of the ordering of those queries. The "LAST_UPDATE_SQL" being the last thing in the DeferredList is not necessarily going to make it happen last. Are the queries in the deferred list supposed to be part of a single transaction?

Not knowing exactly what the SQL queries are here I'm assuming that sometimes a transaction has been setup for your LAST_UPDATE_SQL and sometimes it hasn't been setup depending on the order those runQuery's end up actually running.

Here's how to replace the deferred list with a single adbapi thread using adbapi.runInteraction. I'm not 100% convinced this will fix your issues but I think it's the correct way to write the sort of database interaction you're attempting to do.

class WhoisDb(object):
    # ... shortened ...
    def _get_contacts(self, dom):
        if not dom:
            self.d.errback(UnknownDomain(self._get_limit()))
            return
        self.dom = Domain._make(dom[0])

        d = self.dbpool.runInteraction(
                 self._get_stuff_from_db
            )
        d.addCallback(self._fmt_string)
        d.addErrback(self._fmt_string) # don't forget to add an errback!
        return d

    def _get_stuff_from_db(self, cursor):
        cursor.execute(CON_SQL, (self.dom.dom_owner,)),
        cursor.execute(CON_SQL, (self.dom.dom_admin,)),
        cursor.execute(CON_SQL, (self.dom.dom_tech,)),
        cursor.execute(
            LAST_UPDATE_SQL,
            ( self.dom.domName, )), ] )
        return cursor.fetchall() # or whatever you need to return obviously
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!