private void HandleRowSetResult(Response response) { RequestExecution.ValidateResult(response); var resultResponse = (ResultResponse)response; if (resultResponse.Output is OutputSchemaChange) { //Schema changes need to do blocking operations HandleSchemaChange(resultResponse); return; } RowSet rs; if (resultResponse.Output is OutputRows rows) { rs = rows.RowSet; } else { if (resultResponse.Output is OutputSetKeyspace keyspace) { _session.Keyspace = keyspace.Value; } rs = RowSet.Empty(); } _parent.SetCompleted(null, FillRowSet(rs, resultResponse)); }
/// <summary> /// Starts a new execution and adds it to the executions collection /// </summary> private void StartNewExecution() { try { var execution = new RequestExecution <T>(this, _session, _request); execution.Start(); _running.Add(execution); ScheduleNext(); } catch (NoHostAvailableException ex) { if (_running.Count == 0) { //Its the sending of the first execution //There isn't any host available, yield it to the user SetCompleted(ex); } //Let's wait for the other executions } catch (Exception ex) { //There was an Exception before sending: a protocol error or the keyspace does not exists SetCompleted(ex); } }
/// <summary> /// Gets the retry decision based on the request error /// </summary> internal static RetryDecisionWithReason GetRetryDecisionWithReason( IRequestError error, IExtendedRetryPolicy policy, IStatement statement, Configuration config, int retryCount) { var ex = error.Exception; if (ex is SocketException || ex is OverloadedException || ex is IsBootstrappingException || ex is TruncateException || ex is OperationTimedOutException) { if (ex is SocketException exception) { RequestExecution.Logger.Verbose("Socket error " + exception.SocketErrorCode); } // For PREPARE requests, retry on next host var decision = statement == null && ex is OperationTimedOutException ? RetryDecision.Retry(null, false) : policy.OnRequestError(statement, config, ex, retryCount); return(new RetryDecisionWithReason(decision, RequestExecution.GetErrorType(error))); } if (ex is ReadTimeoutException e) { return(new RetryDecisionWithReason( policy.OnReadTimeout( statement, e.ConsistencyLevel, e.RequiredAcknowledgements, e.ReceivedAcknowledgements, e.WasDataRetrieved, retryCount), RequestErrorType.ReadTimeOut )); } if (ex is WriteTimeoutException e1) { return(new RetryDecisionWithReason( policy.OnWriteTimeout( statement, e1.ConsistencyLevel, e1.WriteType, e1.RequiredAcknowledgements, e1.ReceivedAcknowledgements, retryCount), RequestErrorType.WriteTimeOut )); } if (ex is UnavailableException e2) { return(new RetryDecisionWithReason( policy.OnUnavailable(statement, e2.Consistency, e2.RequiredReplicas, e2.AliveReplicas, retryCount), RequestErrorType.Unavailable )); } // Any other Exception just throw it return(new RetryDecisionWithReason(RetryDecision.Rethrow(), RequestExecution.GetErrorType(error))); }
/// <summary> /// Handles the response of a (re)prepare request and retries to execute on the same connection /// </summary> private void ReprepareResponseHandler(IRequestError error, Response response, Host host) { try { if (error?.Exception != null) { HandleRequestError(error, host); return; } RequestExecution.ValidateResult(response); var output = ((ResultResponse)response).Output; if (!(output is OutputPrepared outputPrepared)) { _parent.SetCompleted( new DriverInternalError("Expected prepared response, obtained " + output.GetType().FullName)); return; } if (_parent.Statement is BoundStatement boundStatement) { // Use the latest result metadata id boundStatement.PreparedStatement.ResultMetadataId = outputPrepared.ResultMetadataId; } Send(_request, host, HandleResponse); } catch (Exception exception) { //There was an issue while sending _parent.SetCompleted(exception); } }
/// <summary> /// Checks if the exception is either a Cassandra response error or a socket exception to retry or failover if necessary. /// </summary> private void HandleException(Exception ex) { RequestExecution.Logger.Info("RequestHandler received exception {0}", ex.ToString()); if (ex is PreparedQueryNotFoundException foundException && (_parent.Statement is BoundStatement || _parent.Statement is BatchStatement)) { PrepareAndRetry(foundException.UnknownId); return; } if (ex is NoHostAvailableException exception) { //A NoHostAvailableException when trying to retrieve _parent.SetNoMoreHosts(exception, this); return; } var c = _connection; if (c != null) { _triedHosts[c.Address] = ex; } if (ex is OperationTimedOutException) { RequestExecution.Logger.Warning(ex.Message); var connection = _connection; if (connection == null) { RequestExecution.Logger.Error("Host and Connection must not be null"); } else { // Checks how many timed out operations are in the connection _session.CheckHealth(connection); } } var decision = RequestExecution.GetRetryDecision( ex, _parent.RetryPolicy, _parent.Statement, _session.Cluster.Configuration, _retryCount); switch (decision.DecisionType) { case RetryDecision.RetryDecisionType.Rethrow: _parent.SetCompleted(ex); break; case RetryDecision.RetryDecisionType.Ignore: // The error was ignored by the RetryPolicy, return an empty rowset _parent.SetCompleted(null, FillRowSet(RowSet.Empty(), null)); break; case RetryDecision.RetryDecisionType.Retry: //Retry the Request using the new consistency level Retry(decision.RetryConsistencyLevel, decision.UseCurrentHost); break; } }
public void SetNoMoreHosts(NoHostAvailableException ex, RequestExecution <T> execution) { //An execution ended with a NoHostAvailableException (retrying or starting). //If there is a running execution, do not yield it to the user _running.Remove(execution); if (_running.Count > 0) { Logger.Info("Could not obtain an available host for speculative execution"); return; } SetCompleted(ex); }
/// <summary> /// Handles the response of a (re)prepare request and retries to execute on the same connection /// </summary> private Action <IRequestError, Response, Host> NewReprepareResponseHandler( PreparedQueryNotFoundException originalError) { void ResponseHandler(IRequestError error, Response response, Host host) { try { if (error?.Exception != null) { HandleRequestError(error, host); return; } RequestExecution.ValidateResult(response); var output = ((ResultResponse)response).Output; if (!(output is OutputPrepared outputPrepared)) { _parent.SetCompleted(new DriverInternalError("Expected prepared response, obtained " + output.GetType().FullName)); return; } if (!outputPrepared.QueryId.SequenceEqual(originalError.UnknownId)) { _parent.SetCompleted(new PreparedStatementIdMismatchException( originalError.UnknownId, outputPrepared.QueryId)); return; } if (_parent.Statement is BoundStatement boundStatement) { // Use the latest result metadata id boundStatement.PreparedStatement.UpdateResultMetadata( new ResultMetadata(outputPrepared.ResultMetadataId, outputPrepared.ResultRowsMetadata)); } Send(_request, host, HandleResponse); } catch (Exception exception) { //There was an issue while sending _parent.SetCompleted(exception); } } return(ResponseHandler); }
/// <summary> /// Handles the response of a (re)prepare request and retries to execute on the same connection /// </summary> private void ReprepareResponseHandler(Exception ex, Response response) { try { if (ex != null) { HandleException(ex); return; } RequestExecution.ValidateResult(response); var output = ((ResultResponse)response).Output; if (!(output is OutputPrepared)) { throw new DriverInternalError("Expected prepared response, obtained " + output.GetType().FullName); } Send(_request, HandleResponse); } catch (Exception exception) { //There was an issue while sending _parent.SetCompleted(exception); } }