我在旋风网络服务器中使用 adbapi。首先,我的处理程序将一些内容写入 SQL 数据库,然后向另一个 Web 服务器发出 HTTP 请求。如果该 HTTP 请求失败,我希望数据库事务回滚。但是,我没有得到那种效果。查看文档,它说
该函数将在线程中使用 twisted.enterprise.adbapi.Transaction 调用,它基本上模仿了 DB-API 游标。在所有情况下,数据库事务将在您的数据库使用完成后提交,除非引发异常,在这种情况下它将回滚。
这并不像我想要的那样精确。我的“数据库使用完成”到底是什么时候?是在调用处理程序的 self.finish() 方法时吗?传递给 ConnectionPool.runInteraction() 的方法何时完成?
这是我的代码
class AccountCreationHandler(BaseRequestHandler):
@cyclone.web.asynchronous
def post(self, accessKey, *args, **kwargs):
try:
d = connPool.runInteraction(self.saveStuffToDatabase)
d.addCallback(self.callWebServer)
d.addCallback(self.formatResult)
d.addErrback(self.handleFailure)
except Exception, e:
self.handleException(e)
def saveStuffToDatabase(self, txn):
txn.execute("INSERT INTO Table1 (f1) VALUES ('v1')")
def callWebServer(self):
agent = Agent(reactor)
hdrs = Headers({ "Content-type": ["application/json"] })
values = json.dumps({ "someField": 123 })
body = SimpleProducer(values)
url = "http://somewebserver.com"
d = agent.request("POST", url, hdrs, body)
d.addCallback(self.handleWebResponse)
return d
def handleWebResponse(self, response):
if response.code == 200:
d = Deferred()
receiver = SimpleReceiver(d)
response.deliverBody(receiver)
d.addCallback(self.saveWebServerResults)
return d
else:
raise Exception("web server failed with http status code %d" % response.code)
def saveWebServerResults(self, body):
self.results = body
def formatResult(self):
self.finish(self.results)
class SimpleProducer(object):
implements(IBodyProducer)
def __init__(self, body):
self.body = body
self.length = len(body)
def startProducing(self, consumer):
consumer.write(self.body)
return succeed(None)
def pauseProducing(self):
pass
def stopProducing(self):
pass
class SimpleReceiver(Protocol):
def __init__(self, d):
self.buf = ''
self.d = d
def dataReceived(self, data):
self.buf += data
def connectionLost(self, reason):
if type(reason.value) == ResponseDone:
self.d.callback(self.buf)
else:
self.d.errback(reason)
如果 Web 服务器抛出错误或与它的连接超时,或者基本上如果代码通过 saveStuffToDatabase 方法,则在发生错误时不会回滚。
我猜这意味着当传递给 ConnectionPool.runInteraction() 的方法完成而没有抛出异常时,事务就被提交了。如果是这样的话,我想我必须把所有东西,包括对 web 服务器的调用同步放在 saveStuffToDatabase() 中?