[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