diff --git a/tools/code/common/Http.cs b/tools/code/common/Http.cs index 1772efc8..2e13475f 100644 --- a/tools/code/common/Http.cs +++ b/tools/code/common/Http.cs @@ -402,6 +402,7 @@ private static bool ShouldRetryInner(HttpMessage message, Exception? exception) (message, exception) switch { ({ Response.Status: 422 or 409 }, _) when HasManagementApiRequestFailedError(message.Response) => true, + ({ Response.Status: 409 }, _) when HasConflictOrPessimisticConcurrencyConflictError(message.Response) && HasOperationOnTheApiIsInProgressMessage(message.Response) => true, ({ Response.Status: 412 }, _) => true, ({ Response.Status: 429 }, _) => true, _ => false @@ -418,6 +419,19 @@ private static bool HasManagementApiRequestFailedError(Response response) => .Where(code => code.Equals("ManagementApiRequestFailed", StringComparison.OrdinalIgnoreCase)) .IsSome; + private static bool HasConflictOrPessimisticConcurrencyConflictError(Response response) => + TryGetErrorCode(response) + .Where(code => + code.Equals("Conflict", StringComparison.OrdinalIgnoreCase) || + code.Equals("PessimisticConcurrencyConflict", StringComparison.OrdinalIgnoreCase) + ) + .IsSome; + + private static bool HasOperationOnTheApiIsInProgressMessage(Response response) => + TryGetMessage(response) + .Where(code => code.Equals("Operation on the API is in progress", StringComparison.OrdinalIgnoreCase)) + .IsSome; + private static Option TryGetErrorCode(Response response) { try @@ -433,6 +447,22 @@ private static Option TryGetErrorCode(Response response) return Option.None; } } + + private static Option TryGetMessage(Response response) + { + try + { + return response.Content + .ToObjectFromJson() + .TryGetJsonObjectProperty("error") + .Bind(error => error.TryGetStringProperty("message")) + .ToOption(); + } + catch (Exception exception) when (exception is ArgumentNullException or NotSupportedException or JsonException) + { + return Option.None; + } + } } public class TelemetryPolicy(Version version) : HttpPipelinePolicy