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 调用。
此代码有时有效,但经常运行约 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 调用。