Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   *      Copyright (C) 2012 DataStax Inc.
   *
   *   Licensed under the Apache License, Version 2.0 (the "License");
   *   you may not use this file except in compliance with the License.
   *   You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
  *   Unless required by applicable law or agreed to in writing, software
  *   distributed under the License is distributed on an "AS IS" BASIS,
  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  *   See the License for the specific language governing permissions and
  *   limitations under the License.
  */
 package com.datastax.driver.core.policies;
 
A retry policy that sometimes retry with a lower consistency level than the one initially requested.

BEWARE: This policy may retry queries using a lower consistency level than the one initially requested. By doing so, it may break consistency guarantees. In other words, if you use this retry policy, there is cases (documented below) where a read at QUORUM may not see a preceding write at QUORUM. Do not use this policy unless you have understood the cases where this can happen and are ok with that. It is also highly recommended to always wrap this policy into LoggingRetryPolicy to log the occurrences of such consistency break.

This policy implements the same retries than the DefaultRetryPolicy policy. But on top of that, it also retries in the following cases:

  • On a read timeout: if the number of replica that responded is greater than one but lower than is required by the requested consistency level, the operation is retried at a lower consistency level.
  • On a write timeout: if the operation is an WriteType.UNLOGGED_BATCH and at least one replica acknowledged the write, the operation is retried at a lower consistency level. Furthermore, for other operation, if at least one replica acknowledged the write, the timeout is ignored.
  • On an unavailable exception: if at least one replica is alive, the operation is retried at a lower consistency level.

The reasoning being this retry policy is the following one. If, based on the information the Cassandra coordinator node returns, retrying the operation with the initially requested consistency has a change to succeed, do it. Otherwise, if based on these information we know the initially requested consistency level cannot be achieve currently, then:

  • For writes, ignore the exception (thus silently failing the consistency requirement) if we know the write has been persisted on at least one replica.
  • For reads, try reading at a lower consistency level (thus silently failing the consistency requirement).
In other words, this policy implements the idea that if the requested consistency level cannot be achieved, the next best thing for writes is to make sure the data is persisted, and that reading something is better than reading nothing, even if there is a risk of reading stale data.
 
 public class DowngradingConsistencyRetryPolicy implements RetryPolicy {
 
 
     private DowngradingConsistencyRetryPolicy() {}
 
     private RetryDecision maxLikelyToWorkCL(int knownOk) {
         if (knownOk >= 3)
             return RetryDecision.retry(.);
         else if (knownOk >= 2)
             return RetryDecision.retry(.);
         else if (knownOk >= 1)
             return RetryDecision.retry(.);
         else
             return RetryDecision.rethrow();
     }

    
Defines whether to retry and at which consistency level on a read timeout.

This method triggers a maximum of one retry. If less replica responded than required by the consistency level (but at least one replica did respond), the operation is retried at a lower consistency level. If enough replica responded but data was not retrieve, the operation is retried with the initial consistency level. Otherwise, an exception is thrown.

Parameters:
query the original query that timeouted.
cl the original consistency level of the read that timeouted.
requiredResponses the number of responses that were required to achieve the requested consistency level.
receivedResponses the number of responses that had been received by the time the timeout exception was raised.
dataRetrieved whether actual data (by opposition to data checksum) was present in the received responses.
nbRetry the number of retry already performed for this operation.
Returns:
a RetryDecision as defined above.
    @Override
    public RetryDecision onReadTimeout(Query queryConsistencyLevel clint requiredResponsesint receivedResponsesboolean dataRetrievedint nbRetry) {
        if (nbRetry != 0)
            return RetryDecision.rethrow();
        if (receivedResponses < requiredResponses) {
            // Tries the biggest CL that is expected to work
            return maxLikelyToWorkCL(receivedResponses);
        }
        return !dataRetrieved ? RetryDecision.retry(cl) : RetryDecision.rethrow();
    }

    
Defines whether to retry and at which consistency level on a write timeout.

This method triggers a maximum of one retry. If writeType == WriteType.BATCH_LOG, the write is retried with the initial consistency level. If writeType == WriteType.UNLOGGED_BATCH and at least one replica acknowledged, the write is retried with a lower consistency level (with unlogged batch, a write timeout can always mean that part of the batch haven't been persisted at all, even if receivedAcks > 0). For other writeType, if we know the write has been persisted on at least one replica, we ignore the exception. Otherwise, an exception is thrown.

Parameters:
query the original query that timeouted.
cl the original consistency level of the write that timeouted.
writeType the type of the write that timeouted.
requiredAcks the number of acknowledgments that were required to achieve the requested consistency level.
receivedAcks the number of acknowledgments that had been received by the time the timeout exception was raised.
nbRetry the number of retry already performed for this operation.
Returns:
a RetryDecision as defined above.
    @Override
    public RetryDecision onWriteTimeout(Query queryConsistencyLevel clWriteType writeTypeint requiredAcksint receivedAcksint nbRetry) {
        if (nbRetry != 0)
            return RetryDecision.rethrow();
        switch (writeType) {
            case :
            case :
                // Since we provide atomicity there is no point in retrying
                return RetryDecision.ignore();
            case :
                // We should not retry counters, period!
                return RetryDecision.ignore();
            case :
                // Since only part of the batch could have been persisted,
                // retry with whatever consistency should allow to persist all
                return maxLikelyToWorkCL(receivedAcks);
            case :
                return RetryDecision.retry(cl);
        }
        return RetryDecision.rethrow();
    }

    
Defines whether to retry and at which consistency level on an unavailable exception.

This method triggers a maximum of one retry. If at least one replica is know to be alive, the operation is retried at a lower consistency level.

Parameters:
query the original query for which the consistency level cannot be achieved.
cl the original consistency level for the operation.
requiredReplica the number of replica that should have been (known) alive for the operation to be attempted.
aliveReplica the number of replica that were know to be alive by the coordinator of the operation.
nbRetry the number of retry already performed for this operation.
Returns:
a RetryDecision as defined above.
    @Override
    public RetryDecision onUnavailable(Query queryConsistencyLevel clint requiredReplicaint aliveReplicaint nbRetry) {
        if (nbRetry != 0)
            return RetryDecision.rethrow();
        // Tries the biggest CL that is expected to work
        return maxLikelyToWorkCL(aliveReplica);
    }
New to GrepCode? Check out our FAQ X