Microsoft Graph API (Календарь) Периодические ошибки 503

Этот код иногда работает, но часто выполняется в течение ~ 20 секунд, а затем выдает сообщение 503 Service Unavailable, когда я вызываю getPage(). Запрос аутентификации / токена работает нормально.

Кажется, я не могу определить какой-либо шаблон, когда он терпит неудачу / преуспевает. Я не верю, что это ошибка дросселирования, поскольку не возвращается заголовок Retry-After, а скрипт запускается только один раз в день ночью и возвращает <200 записей. Я также попытался удалить $filter и изменить порядок параметров, как описано здесь, без явной выгоды.

Может ли кто-нибудь помочь найти здесь причину? Рад поделиться любой дополнительной информацией. Любая помощь очень ценится, спасибо!

<?php
define('DEBUG', true);
session_start();

// set config vars
$ms_url_base = "https://login.microsoftonline.com/d3523db7-f84a-4a24-a815-cd4ba4691c9c";
$ms_client_id = '<client id>';
$ms_redirect_uri = "https://example.com/path";
$ms_scope = "calendars.readwrite user.read";
$ms_client_secret = '<secret>';
$ms_auth_endpoint = '/oauth2/v2.0/authorize';
$ms_token_endpoint = '/oauth2/v2.0/token';
$query_numdays = 100;
if (DEBUG) error_reporting(E_ALL);
date_default_timezone_set("America/Detroit");

require_once __DIR__.'/vendor/autoload.php';

use Microsoft\Graph\Graph;
use Microsoft\Graph\Model;
class EventMod extends \Microsoft\Graph\Model\Event {
    // custom functions here 

    public function getNextLink() {
        parent::getNextLink();
    }
}
class ResponseMod extends \Microsoft\Graph\Http\GraphResponse {}

// authorization
$provider = new Stevenmaguire\OAuth2\Client\Provider\Microsoft([
    'clientId'                  => $ms_client_id,
    'clientSecret'              => $ms_client_secret,
    'redirectUri'               => $ms_redirect_uri,
    'urlAuthorize'              => $ms_url_base.$ms_auth_endpoint,
    'urlAccessToken'            => $ms_url_base.$ms_token_endpoint,
    'urlResourceOwnerDetails'   => 'https://graph.microsoft.com/v2.0/me',
]);

if (!isset($_GET['code'])) {
    $options = ['scope' => $ms_scope, 'aud' => 'Graph'];
    $authUrl = $provider->getAuthorizationUrl($options);
    $_SESSION['oauth2state'] = $provider->getState();
    header('Location: '.$authUrl);
    exit;

} elseif (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state'])) {
    unset($_SESSION['oauth2state']);
    exit('Invalid state');
} else {
    try {
        $token = $provider->getAccessToken('authorization_code', ['code' => $_GET['code']]);
    } catch (League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) {
        exit ("Get access token exception: ".$e->getMessage());
    }

    if (DEBUG) {
        echo 'Access Token: ' . $token->getToken() . "<p>";
        echo 'Refresh Token: ' . $token->getRefreshToken() . "<p>";
        echo 'Expired in: ' . $token->getExpires() . "<p>";
        echo 'Already expired? ' . ($token->hasExpired() ? 'expired' : 'not expired') . "<p>";
    }

    // start calendar query
    $start=new DateTimeImmutable("yesterday 0:0:1");
    $end = $start->add(new DateInterval("P".$query_numdays."D"));

    $url='/me/calendarview'
        .'?startdatetime='.$start->format('c')
        .'&enddatetime='.$end->format('c')
        .'&$filter=isOrganizer+eq+false'
        .'&$select=subject,responseStatus,start,categories'
        .'&$orderby=start/dateTime';

    $graph = new Graph;
    $graph->setAccessToken($token->getToken());
    $data = array();
    try {
        $iterator = $graph->createCollectionRequest("GET", $url)
                    ->setReturnType(EventMod::class)
                    ->addHeaders(["Prefer" => 'outlook.timezone="America/Detroit"'])
                    ->setPageSize(25);
        do {
            $page = $iterator->getPage(); /*************** THIS IS WHERE THE EXCEPTION HAPPENS ************/
            if (DEBUG) echo "<pre>".print_r($page, true)."</pre>";
            $data = array_merge($data, $page);
        } while (!$iterator->isEnd());
    } 
    catch (\Microsoft\Graph\Exception\GraphException $e) {
        if (DEBUG) echo "GraphException Message: ".$e->getMessage();
        exit;
    }
    catch (Exception $e) {
        if (DEBUG) echo "Unk Exception getting data: ".$e->getMessage();
        exit;
    }

    if (DEBUG) print_r($data);
}
?>

composer.json

{
    "require": {
        "microsoft/microsoft-graph": "^1.29",
        "stevenmaguire/oauth2-microsoft": "^2.2"
    }
}

person Nick    schedule 24.04.2021    source источник
comment
Я вижу, что вы используете разбиение на страницы, и это хорошо. В дополнение к этому, просто чтобы изолировать проблему от вашего кода, попробуйте Microsoft Graph Explorer или POSTMAN с указанным выше точным вызовом потока / API и посмотрите, сможете ли вы воспроизвести проблему.   -  person Dev    schedule 28.04.2021
comment
Если я не ошибаюсь, думаю, проблема связана с тем, что вы пытаетесь использовать сложный запрос odata выше - я вижу, что вы используете сочетание фильтров (фильтруйте результаты), select (столбцы), orderby (упорядочивая их). Возможно, вы захотите поиграть с комбинациями, или я бы начал добавлять одну за другой и посмотреть, смогу ли я воспроизвести проблему.   -  person Dev    schedule 28.04.2021
comment
Спасибо за проверку @Dev! Я сократил его до времени начала и окончания, удалив предложения select, filter и orderby. По-прежнему получаю 503. Попробую graph explorer.   -  person Nick    schedule 28.04.2021
comment
конечно, @Nick, дайте мне знать, как это происходит.   -  person Dev    schedule 29.04.2021
comment
Тот же результат в Graph explorer - редко, я получаю ожидаемые результаты мгновенно. Чаще служба недоступна - 503 - 109321 мс   -  person Nick    schedule 29.04.2021
comment
Интересно. Я попытался воспроизвести проблему со своей стороны (с моим почтовым ящиком M365), и это сработало для меня (с ограниченными записями около 200). Пожалуйста, обновите подробную информацию об ошибке, которую вы получили (отметка времени, Requestid).   -  person Dev    schedule 29.04.2021
comment
отредактированный ответ: reasonPhrase = ›Service Unavailable statusCode =› 503 headers = ›Date =› Thu, 29 Apr 2021 15:20:04 GMT Transfer-Encoding = ›chunked Strict-Transport-Security =› max-age = 31536000 идентификатор запроса = ›B9ef0347-19ce-485b-9fe3-bff0dd5d404f client-request-id =› b9ef0347-19ce-485b-9fe3-bff0dd5d404f x-ms-ags-diagnostics = ›{ServerInfo: {DataCenter: North Central US, Slice: E, Кольцо: 3, ScaleUnit: 004, RoleInstance: CH01EPF00003ED2}   -  person Nick    schedule 29.04.2021
comment
Спасибо за обновление @Nick и обновление ответа. Я поиграл с вашим вызовом API, указанным выше, и в итоге заметил проблему - в случае наличия больших больших дат и большого количества данных на моей стороне. Он говорит мне, что сбой произошел из-за тайм-аута клиента. Нам нужно понимать, что представление календаря - это дорогостоящая операция, которая также связана с календарями и добавленными к нему фильтрами. Поэтому я пошел дальше в этом сценарии, уменьшив / минимизируя временное окно для просмотра календаря клиентом, чтобы меньшие отрезки времени сканировались на соответствие календарным событиям. Это помогло мне получить записи, как я ожидал.   -  person Dev    schedule 30.04.2021


Ответы (2)


Я поиграл с вашим вызовом API, указанным выше, и в конце концов заметил проблему - в случае наличия больших больших дат и большого количества данных на моей стороне (не с меньшим временным окном или меньшим количеством записей). Он говорит мне, что сбой произошел из-за тайм-аута клиента. Нам нужно понимать, что представление календаря - это дорогостоящая операция, которая также связана с календарями и добавленными к нему фильтрами. Поэтому я пошел дальше в этом сценарии, уменьшив / минимизируя временное окно для просмотра календаря клиентом, чтобы меньшие отрезки времени сканировались на соответствие календарным событиям. Это помогло мне получить записи, как я ожидал, а также эффективно использовать вызов API Calendarview.

person Dev    schedule 30.04.2021
comment
Не уверен, что это тайм-аут клиента. По крайней мере, не в моем коде. Тайм-аут php был установлен на 60 секунд, и ошибка 503 была возвращена сервером через ~ 20 секунд. Я попытался передать setTimeout (100) в createCollectionRequest () без изменений. Может, тайм-аут происходит на уровне SDK? Также меньшие отрезки времени не будут иметь значения, потому что ошибка связана с одним единственным событием. - person Nick; 01.05.2021
comment
если это связано с одним событием, я бы просто указал на него как на точку контакта, которая приводит к проблеме, а не на API или SDK. Хороший анализ / исследование! - person Dev; 01.05.2021

Видимо проблема была вовсе не в коде. Я обнаружил, что ошибка 503 выдавалась только тогда, когда события определенной даты считывались API. Одно из событий было довольно большим, и я его удалил; после этого скрипт работает нормально.

В этом конкретном мероприятии перечислено 16536 участников, которые, как я полагаю, были источником ошибки. По-прежнему необъяснимо, почему ошибка периодически возникала. В конце концов мне удалось заставить графический проводник успешно прочитать событие, так что, возможно, ошибка находится в Microsoft Graph SDK для PHP. Я отправлю туда сообщение, чтобы узнать, хотят ли разработчики зафиксировать это состояние ошибки.

person Nick    schedule 29.04.2021
comment
о, вау, 16536 участников, перечисленных в конкретном мероприятии - неудивительно, почему у клиента истекло время ожидания, и вы получили HTTP 503. Как я уже сказал выше, вы выполняете дорогостоящую операцию (Calendarview), и это тоже с календарями и фильтрами, добавленными ведущими к этому вопросу. Попробуйте воспользоваться приведенными выше предложениями, чтобы узнать, поможет ли это. Также позвольте мне перейти к ответу, так что он может быть полезен и другим (если это соответствует их сценарию). - person Dev; 30.04.2021
comment
Для справки в будущем это не похоже на проблему тайм-аута клиента - сервер возвращает ошибку 503 задолго до истечения времени ожидания сценария PHP, и передача setTimeout (100) в createCollectionRequest () не дала никакого эффекта. Возможно, проблема с msgraph-sdk-php. Расследование. - person Nick; 01.05.2021
comment
Понятно. Если вы подтвердите, что проблема связана с SDK, я предлагаю вам зарегистрировать проблему в репозитории MS Graph SDK для PHP, чтобы ее можно было исправить. Перед тем как это сделать, просто убедитесь, что вы воспроизвели проблему с последними сборками SDK. - person Dev; 03.05.2021