2012-09-25 88 views
4

我在旋風web服務器中使用adbapi。首先,我的處理程序將一些內容寫入SQL數據庫,然後對另一個Web服務器發出HTTP請求。如果該HTTP請求失敗,我希望數據庫事務回滾。但是,我沒有得到那種效果。綜觀文檔,它說什麼時候扭曲的adbapi事務實際上被提交?

的功能將與 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

對此沒有想法? – d512

回答

2

那麼,我重新實現了代碼使用同步調用,它似乎工作正常。看着爲runInteraction()方法的文檔,它是由多一點明確:

高清runInteraction(自我,互動,* ARGS,** KW):

互動與數據庫並返回結果。 '交互'是一個可調用的對象,它將在使用池連接的線程中執行。它將作爲參數傳遞一個Transaction對象(其接口與您選擇的DB-API模塊的數據庫光標的接口相同),其結果將作爲Deferred返回。 如果運行該方法引發異常,則該事務將被回滾。如果該方法返回一個值,該事務將被提交。

相關問題