Как использовать автоматическую повторную попытку в сервисах Google Drive / Fetcher в Objective C

Эта проблема

Я использую библиотеку https://github.com/google/google-api-objectivec-client для работы с Google Drive API.
Я создаю 10 папок внутри appDataFolder (например) без каких-либо задержек, и это слишком быстро, и я постоянно получаю ошибки для 9/10 моих запросов:

Error Domain=com.google.GTLJSONRPCErrorDomain Code=500 "(Internal Error)" UserInfo={error=Internal Error, NSLocalizedFailureReason=(Internal Error)

some times these:
Error Domain=com.google.GTLJSONRPCErrorDomain Code=403 "(User Rate Limit Exceeded)" UserInfo={error=User Rate Limit Exceeded, NSLocalizedFailureReason=(User Rate Limit Exceeded),

Скорее всего, это связано с исключениями " spamming " или userRateLimit, потому что это легко можно исправить с помощью "sleep" (повторяли это много раз).

Предлагаемое решение

Google предлагает повторить запрос с такого рода ошибками, даже если он предоставляет отличный API, чтобы делать это автоматически. Согласно документации:

Классы обслуживания GTL и класс GTMSessionFetcher обеспечивают механизм автоматической повторной попытки нескольких распространенных сетевых и серверных ошибок с соответствующими увеличивающимися задержками между каждой попыткой. Вы можете включить поддержку автоматического повтора для службы GTL, установив свойство retryEnabled.

// Turn on automatic retry of some common error results
service.retryEnabled = YES;

Повторные ошибки по умолчанию: статус http 408 (тайм-аут запроса), 503 (сервис недоступен) и 504 (тайм-аут шлюза), NSURLErrorNetworkConnectionLost и NSURLErrorTimedOut. Вы можете указать максимальный интервал повторения, отличный от значения по умолчанию, равного 1 минуте, и можете предоставить дополнительный селектор повторов, чтобы настроить критерии для каждой попытки повторения.

Но ошибки со статусом 500 нет в списке по умолчанию. Итак, я попытался использовать это:

// Retry selector is optional for retries.
// If present, it should have the signature:
//   -(BOOL)ticket:(GTLServiceTicket *)ticket willRetry:(BOOL)suggestedWillRetry forError:(NSError *)error
// and return YES to cause a retry.  Note that unlike the fetcher retry
// selector, this selector's first argument is a ticket, not a fetcher.

GTLService.retrySelector

Я создал метод, который постоянно возвращает YES, но он никогда не вызывается и в результате запрос с ошибками не повторяется.

Вопрос

Как использовать автоматическую повторную попытку для google-api-objectivec-client?

Обновить. Пример кода для воспроизведения проблемы:

- (void) reproduceTheIssue: (GTMOAuth2Authentication *) authorizer {

    GTLServiceDrive * driveService = [[GTLServiceDrive alloc] init];
    driveService.retryEnabled = true;
    driveService.authorizer = authorizer;
    //    driveService.fetcherService.retryEnabled = YES; //this also doesn't help
    //    driveService.retrySelector =  @selector(ticket:willRetry:forError:);
    const int DELAY = 0;
    const int NUMBER_OF_FOLDERS = 50;

    for (int i = 0; i < NUMBER_OF_FOLDERS; i++) {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, DELAY * NSEC_PER_SEC), dispatch_get_main_queue(), ^{

            GTLDriveFile * nestedFolder = [GTLDriveFile object];
            NSString * folderName = [NSString stringWithFormat: @"folder-number-%i", i];
            nestedFolder.name = folderName;
            nestedFolder.mimeType = @"application/vnd.google-apps.folder";
            nestedFolder.parents = @[@"appDataFolder"];

            GTLQueryDrive * query = [GTLQueryDrive queryForFilesCreateWithObject: nestedFolder uploadParameters: nil];
            [driveService executeQuery: query completionHandler: ^(GTLServiceTicket * ticket, GTLDriveFile * updatedFile, NSError * error) {
                if (error == nil) {
                    NSLog(@"Successfully created a folder %@", updatedFile);
                } else {
                    NSLog(@"Failed to a folder: %@ error: %@", folderName, error);
                }
            }];
        });
    }
}

- (BOOL) ticket: (GTLServiceTicket *) ticket willRetry: (BOOL) suggestedWillRetry forError: (NSError *) error {
    NSLog(@"I will never be called :( with this arguments ticket: %@, willRetry: %i, error :%@", ticket, suggestedWillRetry, error);
    return YES;
}

Обновление Обновление Проблема обсуждалась на GitHub библиотеки. Краткий ответ: невозможно повторить эту ошибку автоматически. Он должен управляться программно пользователем в handlers,

Логика повторов находится в классе http fetcher, поэтому повторы отражают только ошибки, которые появляются во время сетевых запросов.

0 ответов

Другие вопросы по тегам