1 Reply Latest reply on Oct 26, 2009 6:51 AM by Tim Fox

    transactions & failover

    Jeff Mesnil Master

      I'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?


        • 1. Re: transactions & failover
          Tim Fox Master

           

          "jmesnil" wrote:
          I'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).


          Is this what you raised last week? If so, can you make sure the correct behaviour is tested after you fix it?


          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.


          How can the session be rolled back on the server? The server with the session is dead by this point.


          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.


          Sure, the client shouldn't have to call rollback. But how can you rollback the session on the server - the server with the session is dead/unreachable after a failover attempt.


          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


          Sounds sensible


          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?


          Ok fine.