2012-09-25 1 views
4

나는 cyclone 웹 서버에서 adbapi를 사용하고 있습니다. 먼저 내 처리기가 SQL 데이터베이스에 물건을 쓴 다음 다른 웹 서버에 HTTP 요청을 보낸다. HTTP 요청이 실패하면 데이터베이스 트랜잭션을 롤백해야합니다. 그러나 나는 그 효과를 얻지 못하고있다. 문서를 보면, 그것은트위스티드 adbapi 트랜잭션은 실제로 언제 커밋됩니까?

기능이 기본적으로 DB-API를 커서를 모방 한 twisted.enterprise.adbapi.Transaction와 스레드에서 호출 될 것이라고 말했습니다. 모든 경우에 에서 예외가 발생하지 않는 한 데이터베이스 사용이 완료되면 후에 데이터베이스 트랜잭션이 커밋됩니다.이 경우 롤백됩니다.

이것은 내가 원하는만큼 정확하지 않습니다. 정확하게 "데이터베이스 사용이 완료되었습니다"시점은 언제입니까? 핸들러의 self.finish() 메소드가 호출 될 때인가? ConnectionPool.runInteraction()에 전달 된 메서드가 완료되면? 여기

는 웹 서버가 오류 또는 시간 초과 또는 기본적으로 코드가 saveStuffToDatabase 방법이 바뀌지 경우에 대한 연결을 던지는 경우 내 코드

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) 

때 오류, 아무것도 롤백되지 가져옵니다 발생합니다.

나는 ConnectionPool.runInteraction()에 전달 된 메서드가 예외를 throw하지 않고 끝났을 때 트랜잭션이 커밋되었음을 의미한다고 생각합니다. 그렇다면 saveStuffToDatabase() 내부에서 웹 서버를 동 기적으로 호출하는 것을 포함하여 모든 것을 넣어야한다고 생각하십니까?

+0

이 것에 대해 생각하지 않으십니까? – d512

답변

2

음, 동기 호출을 사용하여 코드를 다시 구현했는데 제대로 작동하는 것처럼 보입니다. runInteraction() 메소드에 대한 설명서를 보면, 그것은 좀 더 분명히 있어요 :

데프 runInteraction (자기, 상호 작용, * 인수, ** kw) :

상호 작용하는 데이터베이스와를 반환 결과. '상호 작용'은 풀링 된 연결을 사용하여 스레드에서 실행되는 호출 가능한 객체입니다. Transaction 객체가 인수로 전달되며 (이 인터페이스는 선택한 DB-API 모듈의 데이터베이스 커서와 동일합니다), 결과는 지연으로 반환됩니다. 메서드를 실행하면 예외가 발생하면 트랜잭션이 롤백됩니다. 메서드가 값을 반환하면 트랜잭션이 커밋됩니다.