< Summary

Class:Microsoft.Azure.Search.IndexBatchException
Assembly:Microsoft.Azure.Search.Data
File(s):C:\Git\azure-sdk-for-net\sdk\search\Microsoft.Azure.Search.Data\src\Customizations\IndexBatchException.cs
Covered lines:23
Uncovered lines:0
Coverable lines:23
Total lines:121
Line coverage:100% (23 of 23)
Covered branches:23
Total branches:24
Branch coverage:95.8% (23 of 24)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
.ctor(...)-100%100%
get_IndexingResults()-100%100%
FindFailedActionsToRetry(...)-100%100%
FindFailedActionsToRetry(...)-100%100%
DoFindFailedActionsToRetry(...)-100%83.33%
CreateMessage(...)-100%100%
IsRetriableStatusCode(...)-100%100%

File(s)

C:\Git\azure-sdk-for-net\sdk\search\Microsoft.Azure.Search.Data\src\Customizations\IndexBatchException.cs

#LineLine coverage
 1// Copyright (c) Microsoft Corporation. All rights reserved.
 2// Licensed under the MIT License. See License.txt in the project root for
 3// license information.
 4
 5namespace Microsoft.Azure.Search
 6{
 7    using System;
 8    using System.Collections.Generic;
 9    using System.Linq;
 10    using Common;
 11    using Models;
 12    using Rest.Azure;
 13
 14    /// <summary>
 15    /// Exception thrown when an indexing operation only partially succeeds.
 16    /// </summary>
 17    public class IndexBatchException : CloudException
 18    {
 19        private const string MessageFormat =
 20            "{0} of {1} indexing actions in the batch failed. The remaining actions succeeded and modified the " +
 21            "index. Check the IndexResponse property for the status of each index action.";
 22
 23        /// <summary>
 24        /// Initializes a new instance of the IndexBatchException class.
 25        /// </summary>
 26        /// <param name="documentIndexResult">The deserialized response from the index request.</param>
 3227        public IndexBatchException(DocumentIndexResult documentIndexResult) : base(CreateMessage(documentIndexResult))
 28        {
 29            // Null check in CreateMessage().
 3230            IndexingResults = documentIndexResult.Results;
 31
 3232            Body = new CloudError() { Code = String.Empty, Message = Message };
 3233        }
 34
 35        /// <summary>
 36        /// Gets the results for the index batch that contains the status for each individual index action.
 37        /// </summary>
 6638        public IList<IndexingResult> IndexingResults { get; }
 39
 40        /// <summary>
 41        /// Finds all index actions in the given batch that failed and need to be retried, and returns them in a
 42        /// new batch.
 43        /// </summary>
 44        /// <param name="originalBatch">The batch that partially failed indexing.</param>
 45        /// <param name="keyFieldName">The name of the key field from the index schema.</param>
 46        /// <returns>
 47        /// A new batch containing all the actions from the given batch that failed and should be retried.
 48        /// </returns>
 49        public IndexBatch<Document> FindFailedActionsToRetry(IndexBatch<Document> originalBatch, string keyFieldName)
 50        {
 4851            string GetKey(Document doc) => doc[keyFieldName].ToString();
 1252            return FindFailedActionsToRetry(originalBatch, GetKey);
 53        }
 54
 55        /// <summary>
 56        /// Finds all index actions in the given batch that failed and need to be retried, and returns them in a
 57        /// new batch.
 58        /// </summary>
 59        /// <typeparam name="T">
 60        /// The CLR type that maps to the index schema. Instances of this type can be stored as documents in the index.
 61        /// </typeparam>
 62        /// <param name="originalBatch">The batch that partially failed indexing.</param>
 63        /// <param name="keySelector">A lambda that retrieves a key value from a given document of type T.</param>
 64        /// <returns>
 65        /// A new batch containing all the actions from the given batch that failed and should be retried.
 66        /// </returns>
 67        public IndexBatch<T> FindFailedActionsToRetry<T>(IndexBatch<T> originalBatch, Func<T, string> keySelector)
 68        {
 2469            IEnumerable<IndexAction<T>> failedActions = DoFindFailedActionsToRetry(originalBatch, keySelector);
 2470            return IndexBatch.New(failedActions);
 71        }
 72
 73        private IEnumerable<IndexAction<T>> DoFindFailedActionsToRetry<T>(IndexBatch<T> originalBatch, Func<T, string> k
 74        {
 14875            IEnumerable<string> allRetriableKeys = IndexingResults.Where(r => IsRetriableStatusCode(r.StatusCode)).Selec
 76
 2477            var uniqueRetriableKeys = new HashSet<string>(allRetriableKeys);
 78
 79            bool ShouldRetry(IndexAction<T> action) =>
 9680                action.Document != null && uniqueRetriableKeys.Contains(keySelector(action.Document));
 81
 2482            return originalBatch.Actions.Where(ShouldRetry);
 83        }
 84
 85        private static string CreateMessage(DocumentIndexResult documentIndexResult)
 86        {
 3287            Throw.IfArgumentNull(documentIndexResult, "documentIndexResult");
 88
 3289            return String.Format(
 3290                MessageFormat,
 16091                documentIndexResult.Results.Count(r => !r.Succeeded),
 3292                documentIndexResult.Results.Count);
 93        }
 94
 95        private static bool IsRetriableStatusCode(int statusCode)
 96        {
 97            switch (statusCode)
 98            {
 99                case 200:
 100                case 201:
 28101                    return false;   // Don't retry on success.
 102
 103                case 404:
 104                case 400:
 24105                    return false;   // Don't retry on user error.
 106
 107                case 500:
 12108                    return false;   // Don't retry when something unexpected happened.
 109
 110                case 422:
 111                case 409:
 112                case 503:
 28113                    return true;    // The above cases might succeed on a subsequent retry.
 114
 115                default:
 116                    // If this happens, it's a bug. Safest to assume no retry.
 4117                    return false;
 118            }
 119        }
 120    }
 121}