Search code examples
pyramidzodbautocommit

When does pyramid commit zodb transaction?


I followed the tutorial on http://docs.pylonsproject.org/docs/pyramid/en/latest/tutorials/wiki/index.html

I know that when I add or change persistent objects (in this case Page objects), the change will not be persisted until transaction.commit() is called. And in order to cancel changes, I can call transaction.abort().

In the tutorial, however, these calls are not shown in the view callables. I assume that there is some middleware in place that will catch exceptions and call .abort() or call .commit() just before sending the HTTP response, but I don't see any mention of it anywhere in the code or config files.

Could you point me in the right direction? I just need to know what happens behind the scenes, so I know if I need to add something myself


Solution

  • The pyramid_tm package is used; it installs a Tween that manages the transaction.

    It simply starts a transaction for every request, and if the request was successful the transaction is committed, and aborted otherwise.

    From the documentation:

    At the beginning of a request a new transaction is started using the transaction.begin() function. Once the request has finished all of its works (ie views have finished running), a few checks are tested:

    • Did some a transaction.doom() cause the transaction to become “doomed”? if so, transaction.abort().
    • Did an exception occur in the underlying code? if so, transaction.abort() If the tm.commit_veto configuration setting was used, did the commit veto callback, called with the response generated by the application, return a result that evaluates to True? if so, transaction.abort().

    If none of these checks calls transaction.abort() then the transaction is instead committed using transaction.commit().

    It'll also retry requests (re-start them from the beginning) if there was a retryable exception (such as a ZODB commit conflict):

    When the transaction manager calls the downstream handler, if the handler raises a “retryable” exception, the transaction manager can be configured to attempt to call the downstream handler again with the same request, in effect “replaying” the request.

    This behaviour is disabled by default; you can set the tm.attempts option to a number larger than 1 to enable it.