我在旋风网络服务器中使用adbapi。首先,我的处理程序将一些内容写入SQL数据库,然后它向另一个Web服务器发出HTTP请求。如果该HTTP请求失败,我希望数据库事务回滚。但是,我没有达到那个效果。看文档,它说
该函数将在带有a的线程中调用 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()的方法完成而没有抛出异常时,事务就会被提交。如果是这种情况,我想我必须把所有内容,包括在saveStuffToDatabase()中同步调用Web服务器?
答案 0 :(得分:1)
好吧,我使用同步调用重新实现了代码,它确实可以正常工作。查看runInteraction()方法的文档,它变得更加清晰:
def runInteraction(self,interaction,* args,** kw):
与数据库交互并返回结果。 'interaction'是一个可调用的对象,它将使用池化连接在线程中执行。它将作为参数传递一个Transaction对象(其接口与您选择的DB-API模块的数据库游标的接口相同),其结果将作为Deferred返回。 如果运行该方法会引发异常,则将回滚该事务。如果方法返回值,则将提交事务。