[Zope3-dev] ZopePublication performs auth outside transaction
Shane Hathaway
shane@zope.com
Fri, 25 Apr 2003 17:43:31 -0400
Jeremy Hylton wrote:
> On Fri, 2003-04-25 at 15:19, Phillip J. Eby wrote:
>
>>There shouldn't BE a "current transaction manager". That's my point. If
>>there is no such thing as a "current" TM, then there is no need to suspend
>>transactions, only to have multiple TM's.
>
>
>>One alternative is to do away with 'get_transaction()' altogether, and
>>simply require ZODB4 apps to create a transaction manager, and explicitly
>>supply it to the ZODB objects that need it. That's not really going to add
>>much code footprint for the simple cases, but it *will* make it abundantly
>>clear how to do anything "advanced" with transactions.
>
>
> To the contrary, it seems like this adds needless complexity to simple
> applications. I don't want to add features for advanced applications
> that come at the cost of extra complexity for simple applications.
get_transaction() is helpful for multi-threaded applications, but a
burden for simple event-driven applications. It could be a big burden
for complex event-driven applications where it's difficult to know the
right places to call suspend()/resume(). In a GUI application, for
example, there is usually no particular entry point for handling events;
event handlers are spread all over the code. Thus, many event-driven
applications should not use get_transaction()--it just adds complexity.
But the lines aren't always so clear. Some applications will combine
the thread model with the event-driven model, especially as people add
things to Zope 3. When event-driven code calls code that assumes
threads and uses get_transaction(), the event-driven code should set the
current transaction (to match an existing transaction) and clear the
current transaction when the call is finished. In fact, there also
ought to be something like "set_no_transaction()" that causes
get_transaction() to fail.
You could implement what I just described using resume() to set the
current transaction and suspend() to clear it. That's not a very
obvious interface, but it would work.
FWIW, here's an unbaked example of a simple GUI class that uses
transactions:
class MyDialog(Dialog):
def __init__(self, db):
self.conn = db.open()
self.conn.setLocalTransaction()
self.data = conn['MyApp'].dialog_data
def onClickedChoice1RadioButton(self, event):
self.data.choice1 = event.button.getValue()
def onClickedChoice2Checkbox(self, event):
self.data.choice2 = event.button.getValue()
def onClickedOk(self, event):
self.conn.getTransaction().commit()
self.close()
def onClickedCancel(self, event):
self.conn.getTransaction().abort()
self.close()
If this had to use get_transaction(), each of the 4 event handlers would
have to resume() and suspend() to avoid getting mixed up with
simultaneous dialogs and/or windows. The GUI framework might provide a
way to invoke some code before and after all event handlers, but it
might not, and it's cleaner to just not have to do that.
Shane