Well, just as a data point, in Zope (where you always get a transaction whether you like it or not, and aren't given any control over how it works) this has kicked me in the ass before. It's also usually nice. But the ass-kicking really sucks. One of Zope's features is that if you get a conflict error, it'll re-run the request for you, essentially creating a situation where when contention gets high you don't require the user to hit submit over and over, you hit submit over and over *for* the user. Lovely.

In my experience, Zope is a valuable data point for how *not* to do things. Like you, my ass still has bruises from Zope 2. I hope this doesn't negate my initial argument :)

That said, there certainly is a genuine appeal to putting everything in transactions.

Agreed, and it appears that Kevin agrees.

The only other alternative that I can think of, is to automatically realize when you need to run inside a transaction by having SQLObject start one automatically when a create, update, or delete occurs and then have TurboGears commit or rollback any open transactions at the conclusion of a request depending on whether or not an "exceptional" Exception occurred.

SQLObject can't current do this, but I don't think this would be too difficult. Basically you'd create another Transaction subclass, and it would watch for updating methods, and would only start using its own transactional connection once one had gone by. I think this could reduce the likelihood of contention quite a bit, so long as you aren't too concerned about absolutely isolated transactions. I.e., your first select may not be consistent with your second select, but if you run that in a transaction (with the right isolation) it would be.

Given that this is also possible, it seems like there are several different ways to do this off the top of my head:

  1. WSGI middleware (I think)
  2. CherryPy filters
  3. SQLObject modifications
  4. Decorators
  5. Some mixture of the above

What is the best way? I have no idea, but I am intrigued by option #3, because I thought it might be hard, and it would take into account the actual use of the model objects automatically... of course it doesn't take into account anything that happens directly against the DB not through SQLObject...

That being said, I really don't know what the best option is. Kevin, have you decided on a direction to take here? How can I help?

There are some open caching issues with transactions as well, that require some thinking about what has to be expired when. And, really, transactions could probably make more use of caching than they currently do.

I am very interested in the direction that you are planning on taking, and how I can help.

  -- Jonathan

Reply via email to