Microsoft Graph API(日历)间歇性 503 错误

Microsoft Graph API (Calendar) Intermittent 503 Errors

此代码有时有效,但经常运行约 20 秒,然后在我调用 getPage() 时失败并显示“503 服务不可用”消息。 authentication/token 请求似乎工作正常。

我似乎无法确定它 fails/succeeds 时的任何模式。我不认为这是一个限制错误,因为没有返回“Retry-After”header,并且该脚本每天晚上只运行一次,返回的记录少于 200 条。我还尝试删除 $filter 并按照 here 所述更改参数顺序,但没有明显的好处。

谁能帮忙找出原因吗?很高兴分享任何其他信息。非常感谢任何帮助,谢谢!

<?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"
    }
}

显然问题根本不在代码中。我发现仅当 API 读取特定日期的事件时才会抛出 503 错误。其中一个事件相当大,我删除了它;在此之后脚本运行良好。

此特定事件列出了 16536 名与会者,我认为这是错误的来源。仍然无法解释为什么错误是间歇性的。我最终能够得到graph explorer to successfully read the event, so perhaps the bug is in the Microsoft Graph SDK for PHP。我会 post 去看看开发者是否想捕获这个错误情况。

我玩了你上面的 API 电话,我最终注意到了这个问题 - 如果我有更大的日期和大量的数据(而不是更短的时间 window 或记录较少)。它告诉我失败是由于客户端超时。我们需要了解,当您处理添加到其中的日历和过滤器时,日历视图也是一项昂贵的操作。所以我在这种情况下继续进行,reduce/minimize 时间 window 用于客户端的日历视图,因此扫描更小的时间段以匹配日历事件。它帮助我获得了预期的记录,并有效地利用了 Calendarview API 调用。