Клиент Google API для .NET: как реализовать экспоненциальный откат - PullRequest
0 голосов
/ 02 декабря 2018

Я создал метод для добавления участников группового запроса в группу Google с помощью ядра .NET и клиентской библиотеки Google .NET.Код выглядит следующим образом:

private void InitializeGSuiteDirectoryService()
{
    _directoryServiceCredential = GoogleCredential
        .FromJson(GlobalSettings.Instance.GSuiteSettings.Credentials)
        .CreateScoped(_scopes)
        .CreateWithUser(GlobalSettings.Instance.GSuiteSettings.User);

    _directoryService = new DirectoryService(new  BaseClientService.Initializer()
    {
        HttpClientInitializer = _directoryServiceCredential,
        ApplicationName = _applicationName
    });
}

public OperationResult<int> AddGroupMembers(Group group, IEnumerable<Member> members)
{
    var result = new OperationResult<int>();
    var memberList = members.ToList();
    var batchRequestCount = 0;

    if (memberList.Any())
    {
        var request = new BatchRequest(_directoryService);

        foreach (var member in memberList)
        {
            batchRequestCount++;
            request.Queue<Members>(_directoryService.Members.Insert(member, group.Id), (content, error, i, message) =>
            {
                if (message.IsSuccessStatusCode)
                {
                    //log OK
                }
                else
                {
                    // Implement Exponential backoff only on the request that failed.
                }
            });
            if (batchRequestCount == 30|| member.Equals(memberList.Last()))
            {
                request.ExecuteAsync().Wait();
                request = new BatchRequest(_directoryService); //Clear queue
            }
        }
    }

    return result;
}

Логика работает нормально, если количество членов мало;однако, когда число участников, скажем, 100 (это максимальное количество пользователей в тестовом экземпляре моего Google), я получаю сообщение об ошибке от Google, которое гласит: «quotaExceeded».В соответствии с документацией Google ограничение на пакетный запрос в их Admin SDK составляет 1000, и я установил для своей логики значение Выполнить, когда мы достигнем предела 30.

ВОПРОС:Как мне реализовать обработку ошибок, чтобы повторить всякий раз, когда я получаю эту ошибку?Их документация предлагает реализовать «экспоненциальный откат» с ответом, который содержит «ошибку повторения» (я не вижу этого, когда проверяю свой ответ).

1 Ответ

0 голосов
/ 04 декабря 2018

Итак, вот что я в итоге сделал для реализации экспоненциального отката по моему призыву добавить членов в группу Gsuite.Так как я использую ядро ​​dotnet, я смог использовать ' Polly ', которая является библиотекой устойчивости и обработки переходных сбоев, которая предлагает эту функциональность из коробки.Может возникнуть некоторая необходимость в рефакторинге, но вот как выглядит код на данный момент:

    public OperationResult<int> AddGroupMembers(Group group, IEnumerable<Member> members)
    {
        var result = new OperationResult<int>();
        var memberList = members.ToList();
        var batchRequestCount = 0;

        if (memberList.Any())
        {
            var request = new BatchRequest(_directoryService);

            foreach (var member in memberList)
            {
                retryRequest = false; // This variable needs to be declared at the class level to guarantee the value is available to the original thread running the process.
                batchRequestCount++;
                request.Queue<Members>(_directoryService.Members.Insert(member, group.Id), (content, error, i, message) =>
                {
                    // If error code is 'quotaExceeded' retry the request ( You can add as many error codes as you'd like to retry here) 
                    if (error.Code == 403)
                    {
                        retryRequest = true;
                    }

                });

                // Execute batch request to add members in batches of 30 member max
                if (batchRequestCount == 30|| member.Equals(memberList.Last()))
                {

                    // Below is what the code to retry using polly looks like
                    var response = Policy
                        .HandleResult<HttpResponseMessage>(message => message.StatusCode == HttpStatusCode.Conflict)
                        .WaitAndRetry(new[]
                        {
                            TimeSpan.FromSeconds(1),
                            TimeSpan.FromSeconds(2),
                            TimeSpan.FromSeconds(4)
                        }, (results, timeSpan, retryCount, context) =>
                        {
                            // Log Warn saying a retry was required.
                        })
                        .Execute(() =>
                        {
                            var httpResponseMsg = new HttpResponseMessage();

                            // Execute batch request Synchronously
                            request.ExecuteAsync().Wait();
                            if (retryRequest)
                            {
                                httpResponseMsg.StatusCode = HttpStatusCode.Conflict;
                                retryRequest = false;
                            }
                            else
                            {
                                httpResponseMsg.StatusCode = HttpStatusCode.OK;
                            }

                            return httpResponseMsg;
                        });
                    if (response.IsSuccessStatusCode)
                    {
                       // Log info
                    }
                    else
                    {
                        // Log warn
                    }

                    requestCount = 0;
                    request = new BatchRequest(_directoryService);
                    batchCompletedCount++;
                }
            }
        }

        return result;
    }
...