nl_tokens: / * ( non - Javadoc )
pl_tokens: @ Override public < R > R transactNew ( final ObjectifyImpl parent , int limitTries , final Work < R > work ) { Preconditions . checkArgument ( limitTries >= 1 ) ; final int ORIGINAL_TRIES = limitTries ; while ( true ) { try { return transactOnce ( parent , work ) ; } catch ( DatastoreException ex ) { // This doesn't work because the SDK considers all transactions to be non-retryable. Objectify has always
   // assumed that transactions are idempotent and retries accordingly. So we have to explicitly check against
   // code 10, which is ABORTED. https://cloud.google.com/datastore/docs/concepts/errors
   //				if (!ex.isRetryable())
   //					throw ex;
   // I hate this so much. Sometimes the transaction gets closed by the datastore during contention and
   // then it proceeds to freak out and 503.
   if ( Code . ABORTED . getNumber ( ) == ex . getCode ( ) || ( Code . INVALID_ARGUMENT . getNumber ( ) == ex . getCode ( ) && ex . getMessage ( ) . contains ( "transaction closed" ) ) ) { // Continue to retry logic
   } else { throw ex ; } if ( -- limitTries > 0 ) { log . warn ( "Retrying {} failure for {}: {}" , ex . getReason ( ) , work , ex ) ; log . trace ( "Details of transaction failure" , ex ) ; try { // Do increasing backoffs with randomness
   Thread . sleep ( Math . <mask> ( 10000 , ( long ) ( 0.5 * Math . random ( ) + 0.5 ) * 200 * ( ORIGINAL_TRIES - limitTries + 2 ) ) ) ; } catch ( InterruptedException ignored ) { } } else { throw new DatastoreException ( ex . getCode ( ) , "Failed retrying datastore " + ORIGINAL_TRIES + " times " , ex . getReason ( ) , ex ) ; } } } }