[Persistence-sig] "Straw Man" transaction API

Shane Hathaway shane@zope.com
Mon, 29 Jul 2002 22:46:27 -0400 (EDT)


On Mon, 29 Jul 2002, Jeremy Hylton wrote:

> Last week, I worked out a revised transaction API for user code and
> for data managers.  It's implemented in ZODB4, but is fairly
> preliminary code.  I imagine we'll revise it further, but I'd like to
> describe the changes briefly.

This is great work.

> (snip)
>
> The APIs look like this:
>
> class ITransaction(Interface):
>     """Transaction objects."""
>
>     def abort():
>         """Abort the current transaction."""
>
>     def begin():
>         """Begin a transaction."""
>
>     def commit():
>         """Commit a transaction."""
>
>     def join(resource):
>         """Join a resource manager to the current transaction."""

By "resource manager" do you mean "IDataManager"?

>
>     def status():
>         """Return status of the current transaction."""

What kind of object would status() return?  Who might make use of it?

Also, I'd like to see some way to set transaction metadata.

> class IDataManager(Interface):
>     """Data management interface for storing objects transactionally."""
>
>     def prepare(transaction):
>         """Begin two-phase commit of a transaction.
>
>         DataManager should return True or False.
>         """
>
>     def abort(transaction):
>         """Abort changes made by transaction."""
>
>     def commit(transaction):
>         """Commit changes made by transaction."""
>
>     def savepoint(transaction):
>         """Do tentative commit of changes to this point.
>
>         Should return an object implementing IRollback
>         """

I would like this interface to be called ITransactionParticipant.  There
are many interesting kinds of objects that would be interested in
participating in a transaction, and not all of them have the immediate
responsibility of storing data.  But the names you chose for the methods
are very clear and concise, I think.

> class IRollback(Interface):
>
>     def rollback():
>         """Rollback changes since savepoint."""
>
> I think the rollback mechanism will work well enough.  Gray and Reuter
> explain that it can be used to simulate a nested transaction
> architecture.  Thus, I think it's a reasonable building block for the
> nested transaction API.

Making rollback operations into objects is a little surprising, but as I
don't fully understand the ideas behind nested transactions, I'm sure
there's a reason for rollback objects to exist. :-)

> I think I'm also in favor of the new abort semantics.  ZODB3 would
> abort the transactions -- call abort() on all the data managers -- if
> an error occurred during a commit.  The new code requires that the
> user do this instead.  I think that's better, because it leaves the
> state of the objects intact if the code wants to analyze what went
> wrong before retrying the transaction.
>
> Note that a Transaction doesn't have a register method.  Instead, a
> modified object calls register() on its data manager.  The data
> manager can join() that transaction if that's the right thing to do.
> The ZODB Connection joins on the first register call of the
> transaction.  However, I currently have join() on the transaction, not
> the Transaction.Manager (aka TP monitor).
>
> I'm in favor of sticking with register() as the persistent method,
> although notify() would be okay, too.  I imagine that some data
> managers would want to be notified when an object is read or written.
> In that case, I'm not sure if notify() is enough; we might want a
> notify method for each kind of event or a notify() method with the
> event as an argument.

It seems to me that the data manager should register to receive specific
notifications.  Some data managers are only interested in knowing when an
object is moving from "ghost" to "saved" and from "saved" to "changed"
state (such as ZODB); others might want more events, like being notified
the first time an object is read in a transaction or receiving
notification of *every* attribute change.  Supporting the extra events in
C only incurs a speed penalty if the data manager requests those events.

Shane