CycloneWebサーバーで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サーバーがエラーをスローした場合、またはWebサーバーへの接続がタイムアウトした場合、または基本的にコードがsaveStuffToDatabaseメソッドを通過した場合、エラーが発生しても何もロールバックされません。
これは、ConnectionPool.runInteraction()に渡されたメソッドが例外をスローせずに終了したときに、トランザクションがコミットされることを意味していると思います。その場合、Webサーバーへの呼び出しを含むすべてをsaveStuffToDatabase()内に同期的に配置する必要があると思いますか?