Caleb
Thanks
-Vincent
On Jan 10, 2011, at 2:15 PM, Caleb James DeLisle wrote:
> Hi,
> I have been working hard on filesystem attachments and I found that
synchronizing manual filesystem
> transactions with automatic database
transactions was a difficult job
and I needed a new tool to do
> it. So I wrote what I am proposing to be the
next XWiki Persistence
Engine.
>
> I'll start off with the fun part of the proposal, I have been calling it
xwiki-store so far but I am
> so excited about the capabilities of this
engine that I don't think it
does it justice to name it
> "store" after the place on the
corner with milk and eggs. I am proposing
it be named "XWiki
> Persistence Engine", the directory will
be renamed xwiki-persistence,
the artifact name
> xwiki-core-persistence, and the package name
org.xwiki.persistence.
Persistence is an attribute of
> castles, mountains and redwood trees which I
think is fitting for a
conservatively designed storage
> engine.
>
> Now a little explanation of what I'm so excited about:
> The common and error prone way of saving things in the database is to
open a
transaction, enter a
> try clause, do something then commit. If we
catch an exception, then we
rollback.
> something like this:
>
> begin transaction;
> try {
> do something;
> do something else;
> commit;
> } catch (Any exception which may occur) {
> rollback;
> }
>
> There are 3 things which can go wrong. 1 we forget to begin the
transaction, 2
we forget to commit
> and 3 we do not rollback properly. What makes
things worse is often the
database will "assume we
> meant to..." and things will work ok
most of the time which makes things
much worse because bugs
> will hide very well.
>
> My answer to this problem is a class called TransactionRunnable. It
provides a
set of 5 empty
> methods to override: onPreRun(), onRun(),
onCommit(), onRollback(), and
onComplete(). the exact
> circumstances under which each are called is
documented in the javadoc
comments here:
>
http://svn.xwiki.org/svnroot/xwiki/contrib/sandbox/xwiki-store/xwiki-store-…
> I wrote TransactionRunnable twice, I wrote
it, used it for attachments,
then after having real
>> experience as a user, I wrote it again.
>
>> To repeat our original example
with TransactionRunnable you might say
this:
>
>> public class
DoSomethingTransactionRunnable extends TransactionRunnable
>> {
>> public void onRun()
>> {
>> do something;
>> do something else;
>> }
>> }
>
>> Now we can use another
TransactionRunnable which opens and closes the
transaction for us.
>
>> StartableTransactionRunnable
transaction = new
HibernateTransactionRunnable();
>> new DoSomethingTransactionRunnable().runIn(transaction);
>> transaction.start();
>
>> the runIn() function allows us
to run one TransactionRunnable inside of
another. Supposing we wanted
> to reuse "do something else" in
other places, we can make it a separate
TransactionRunnable and use
> the runIn() function to hook it to our
DoSomethingTransactionRunnable
ie:
>
>> public class
DoSomethingTransactionRunnable extends TransactionRunnable
>> {
>> public DoSomethingTransactionRunnable()
>> {
>> new DoSomethingElseTransactionRunnable().runIn(this);
>> }
>> ..
>
>> The only limitations on
running TransactionRunnables inside of one
another are they cannot run more
> than once and they cannot call themselves
(this would be an infinite
loop).
>
>> This pattern makes each job
which is done on storage easily isolated
and, as I have so far
> experienced, trivial to test. However, it
still leaves the possibility
that we might forget that
> DoSomethingTransactionRunnable must be run
inside of a hibernate
transaction. I have devised a
> solution for this too. Using generics, I
offered a means for the author
of a TransactionRunnable to
> communicate to the compiler what other
TransactionRunnable their
runnable must be run in and without
> explicit casting or defining of an
intermediary runnable, this
requirement cannot be violated or
>> else it wouldn't compile!
>
>> Finally we have the issue of
starting the runnable. Who's to say I won't
be tired one day and just
> write new
DoSomethingTransactionRunnable().start() without opening a
transaction first? If
> DoSomethingTransactionRunnable cannot be
safely run outside of a
transaction all it needs to do is
> not extend StartableTransactionRunnable and
it won't have any start
function.
>
>> I have taken a multitude of
very easy mistakes and given the author of a
TransactionRunnable the
> tools to make it very hard for the user to
make them. Also, since a
TransactionRunnable has no
> reason to be very long (it can just branch
off into another runnable)
this will make testing and
> code review easy in the place where it is
most important. This part of
the code is entirely generic
>> and has no dependence on hibernate or anything else.
>
>> I propose we move:
>> contrib/sandbox/xwiki-store/xwiki-store-transaction/
>> to:
>> platform/core/xwiki-persistence/xwiki-persistence-transaction
>
>> And I will propose moving each
additional piece in the coming days.
>
>> WDYT?
>
>> Caleb
>
> _______________________________________________
> devs mailing list
> devs(a)xwiki.org
>
http://lists.xwiki.org/mailman/listinfo/devs
>
_______________________________________________
devs mailing list
devs(a)xwiki.org
http://lists.xwiki.org/mailman/listinfo/devs