Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 31 additions & 3 deletions csharp/src/Drivers/Databricks/RetryHttpHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

using System;
using System.Diagnostics;
using System.Net;
using System.Net.Http;
using System.Threading;
Expand Down Expand Up @@ -52,6 +53,8 @@ protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
Activity? activity = Activity.Current;

// Clone the request content if it's not null so we can reuse it for retries
var requestContentClone = request.Content != null
? await CloneHttpContentAsync(request.Content)
Expand All @@ -77,11 +80,20 @@ protected override async Task<HttpResponseMessage> SendAsync(
// If it's not a retryable status code, return immediately
if (!IsRetryableStatusCode(response.StatusCode))
{
// Only log retry summary if retries occurred
if (attemptCount > 0)
{
activity?.SetTag("http.retry.total_attempts", attemptCount);
activity?.SetTag("http.response.status_code", (int)response.StatusCode);
}
return response;
}

attemptCount++;

activity?.SetTag("http.retry.attempt", attemptCount);
activity?.SetTag("http.response.status_code", (int)response.StatusCode);

// Check if we've exceeded the timeout
TimeSpan elapsedTime = DateTime.UtcNow - startTime;
if (_retryTimeoutSeconds > 0 && elapsedTime.TotalSeconds > _retryTimeoutSeconds)
Expand Down Expand Up @@ -138,14 +150,30 @@ protected override async Task<HttpResponseMessage> SendAsync(
currentBackoffSeconds = Math.Min(currentBackoffSeconds * 2, _maxBackoffSeconds);
} while (!cancellationToken.IsCancellationRequested);

activity?.SetTag("http.retry.total_attempts", attemptCount);
activity?.SetTag("http.response.status_code", (int)response.StatusCode);

// If we get here, we've either exceeded the timeout or been cancelled
if (cancellationToken.IsCancellationRequested)
{
throw new OperationCanceledException("Request cancelled during retry wait", cancellationToken);
activity?.SetTag("http.retry.outcome", "cancelled");
var cancelEx = new OperationCanceledException("Request cancelled during retry wait", cancellationToken);
activity?.AddException(cancelEx, [
new("error.context", "http.retry.cancelled"),
new("attempts", attemptCount)
]);
}

throw new DatabricksException(lastErrorMessage ?? "Service temporarily unavailable and retry timeout exceeded", AdbcStatusCode.IOError)
.SetSqlState("08001");
// Timeout exceeded
activity?.SetTag("http.retry.outcome", "timeout_exceeded");
var exception = new DatabricksException(lastErrorMessage ?? "Service temporarily unavailable and retry timeout exceeded", AdbcStatusCode.IOError).SetSqlState("08001");
activity?.AddException(exception, [
new("error.context", "http.retry.timeout_exceeded"),
new("attempts", attemptCount),
new("total_retry_seconds", totalRetrySeconds),
new("timeout_seconds", _retryTimeoutSeconds)
]);
throw exception;
}

/// <summary>
Expand Down
Loading