transactions & failover
jmesnil Oct 26, 2009 6:29 AMI'm looking at the new semantics for replication and how they relate to transactions.
I have spotted a few disprecancies between the code, the tests and my expectations that I need to clear to document replication changes.
1. work done by a transaction
1. create consumer 2. start session 3. send messages 4. commit session 5. crash live server + failover 6. commit session
Failover tests assumes that commit at step 6 must succeed since no work has been done betwee the commit at #4 and failover at #5.
But this is not the case: after commit at #4, messages are delivered to the consumer and the session must be flagged as workDone.
There is a race condition in the code, where workDone is set to false after committing the session. It should be set *before* as committing the session can get work done (e.g. deliver messages to consumer on the same session).
2. Commit a rollback-only session after failover
If there was work done when the failover occurs, the session is flagged as rollbackonly.
When the user calls session.commit, it gets a HornetQException.TX_ROLLEDBACK but the session is never rolled back on the server.
I don't think it is up to the user to catch the HornetQException and calls session.rollback() in that case.
I think when the session is flagged as rollback-only, the session must be rolled back and, after, an exception must be thrown to the client.
3. Continue to use a rollback only session
If a session is flagged as rollback only, rolling it back does not clear its status.
I think this should be possible
1. do work 2. failover occurs => session is flagged as rollback-only 3. commit the session => rollback the session as it is rollback-only 4. do other work 5. commit the session => this should work but it doesn't as the session remains flagged as rollback-only
I think that if a rollback-only session is rolled back, we should clear its flag so that it can be possible to commit again later on
4. Rollback-only status
As there is no way to know the rollback-only status of a session, the user has no other choice currently than writing:
try { session.commit(); } catch(HornetQException e) { if (e.getCode() == TRANSACTION_ROLLED_BACK) { session.rollback(); session.close(); } }
Either we need to make sure that committing a rollback-only session will effectively rollback the session or we need to add a isRollbackOnly() method to the session to know its status.
imho, making sure to rollback a rollback-only session is much cleaner.
wdyt?