[Glass] Nested transactions and 'CorruptObj error', or: how to abort in GLASS?

Pieter Nagel pieter at nagel.co.za
Tue Mar 25 07:14:48 PDT 2014


I'm happy to report that our problems with aborting under Seaside in GS3
are now solved, thanks to advice that I received off-list from Michael
Veigl.

For the sake of others with this question who may search the archive, I
reproduce his email below, with his permission:

--- snip ---

Hello Pieter,

We are in the same situation that out of a couple of subsequent actions
one might
fail and every change done before must be rolled back to avoid
inconsistencies.
Maybe our approach can help you, it is similar to yours but does not use
native
nested transactions.
As you know aborting from within a seaside application is not recommended,
however
committing "carefully" should not do harm. Thus we split up execution of
our domain
code into two steps. You could as well say, we wrap our code into some
transaction
handler.
So the steps are these:

1. Do a commit
We assume that a commit prior to any changes generated by our domain logic
will not
lead to inconsistencies within continuations and other seaside specific data.
Such a commit however should be checked for conflicts already at this
time. Our code
fragment looks like this:
        System _validateTransaction <= 0 ifFalse: [WARetryHttpRequest
signal: 'Transaction
would not commit, retry'].
        System commitTransaction.
        System inTransaction ifFalse: [System beginTransaction]

2. Perform your domain specific code and check the result
        a. In case of an error do an abort:
                System inTransaction ifTrue: [System abortTransaction].
                System beginTransaction
        The abort is safe because seaside state has been saved before
        b. If everything goes well just continue, the seaside framework
will commit later on

It is worth mentioning that you have to guarantee the session being in a
transaction
when leaving your domain code, otherwise seaside's own commit would fail.
In 2.a.
#beginTransaction could be executed conditionally depending on the session
being in
transaction or not.

I hope you get the idea and it works out for you.

Good luck,
Michael Veigl

--- snip ---

The only thing I changed is, I do not call _validateTransaction before
commitTransaction. This reads to me like a potential race condition: what
if between the validate and commit something happens that will make the
commit fail?

Instead, I call commitTransaction and then do the WARetryHttpRequest in
case of failure, since commitTransaction will then either commit or fail
atomically.



More information about the Glass mailing list