API呼び出しリカバリー:失敗したリクエストの適切な処理
注釈:本資料はAI技術を用いて翻訳されています。
ゲームがバックエンドサービスへの接続を失い、API リクエストを複数回送信しても成功レスポンスを受信できない場合、適切なエラーハンドリングが重要です。これがないと、プログレスの保存、フレンドリストの更新、マッチメイキングなどの特定の機能が正常に動作しなくなり、プレイヤーのフラストレーションの原因となります。
これを回避するために、失敗した API 呼び出しを適切に処理するフォールバック機能の追加を検討してください。具体的には、接続が復旧するまでデータを一時的にローカルに保存したり、状況をプレイヤーに知らせるわかりやすいメッセージを表示したりすることが考えられます。これらの小さな配慮が、ネットワークの問題が発生した場合でも、ゲーム体験をスムーズで楽しいものに保つ上で大きな違いを生み出します。
API 関数を使用する際は、リクエストが失敗する状況を処理することが重要です。リクエストが通らない場合、ゲームはエラーや悪いプレイヤー体験を防ぐ方法で応答する必要があります。
HTTP エラーコード
- Unreal Engine
- Unity
API リトライシステムは、以下のHTTPエラーコードのいずれかに遭遇した場合、自動的にリトライを試行します:
- 429 (Too Many Requests) - サーバーが一度に多すぎるリクエストを受信している。
- 449 (Retry With) - リクエストを異なる条件でリトライする必要がある。
- 500 (Server Error) - サーバー内部でエラーが発生した。
- 502 (Bad Gateway) - サーバーが別のサービスから無効なレスポンスを受信した。
- 503 (Service Unavailable) - サーバーが一時的に利用できない。
- 504 (Gateway Timeout) - サーバーの応答がタイムアウトした。
API リトライシステムは、HTTPエラーに遭遇した場合、自動的にリトライを試行します。
HTTP リトライメカニズム
- Unreal Engine
- Unity
HTTP リトライ設定は、Unreal Engine SDK 内の AccelByteHttpRetryScheduler.cpp で定義されており、次のリトライ試行を計算するロジックは AccelByteHttpRetryTask.cpp ファイル内の FHttpRetryTask::ScheduleNextRetry() で処理されます。
int FHttpRetryScheduler::InitialDelay = 1; // 次のリトライ試行までの初期遅延(秒)
int FHttpRetryScheduler::MaximumDelay = 30; // 次のリトライ試行までの最大遅延(秒)
int FHttpRetryScheduler::TotalTimeout = 60; // リトライの総タイムアウト(秒)
リトライタイミングの動作方法:
- 最初のリトライは初期遅延(デフォルトは1秒)で開始されます。
- 各リトライ遅延は前回の2倍になります。
- 小さなランダムバリエーションが追加されます。これは、-次の遅延から+次の遅延までの値を取り、それを4で割って遅延に適用することで行われます。これにより、リトライが完全に予測可能な間隔で発生することを防ぎます。
- 遅延は最大制限(デフォルトは30秒)を超えることはありません。これを超える場合は、最大遅延でキャップされます。
- リトライに費やされた総時間が総タイムアウト(デフォルトは60秒)を超える場合、システムはリトライを停止し、エラーコード
ErrorCodes::NetworkError(14005) を返します。
このリトライメカニズムは、迅速なエラー回復とサーバーに問題がある際の過度なリクエストの回避のバランスを取るのに役立ちます。
リトライメカニズムはデフォルトで実装されており、以下のバージョンでリリースされました:
HTTP リトライ設定は、Unity SDK の AccelByteHttpClient.cs 内の SetRetryParameters() で定義されており、次のリトライ試行を計算するロジックは SendRequestAsync() 関数で処理されます。
public void SetRetryParameters(uint totalTimeoutMs = 60000, uint initialDelayMs = 1000, uint maxDelayMs = 30000, uint maxRetries = 3)
{
this.totalTimeoutMs = totalTimeoutMs;
this.initialDelayMs = initialDelayMs;
this.maxDelayMs = maxDelayMs;
this.maxRetries = maxRetries;
}
リトライタイミングの動作方法:
- 最初のリトライは初期遅延(デフォルトは1秒)で開始されます。
- 各リトライ遅延は前回の2倍になります。
- 小さなランダムバリエーションが追加されます。これは、-次の遅延から+次の遅延までの値を取り、それを4で割って遅延に適用することで行われます。これにより、リトライが完全に予測可能な間隔で発生することを防ぎます。
- 遅延は最大制限(デフォルトは30秒)を超えることはありません。これを超える場合は、最大遅延でキャップされます。
- リトライに費やされた総時間が総タイムアウト(デフォルトは60秒)を超える場合、システムはリトライを停止し、エラーコード
ErrorCode.NetworkError(14005) を返します。
このリトライメカニズムは、迅速なエラー回復とサーバーに問題がある際の過度なリクエストの回避のバランスを取るのに役立ちます。
リトライメカニズムはデフォルトで実装されており、以下のバージョンでリリースされました:
- Unity SDK 15.17.0
HTTP リトライ設定は、一時的なネットワーク問題を自動的に処理するように設計されており、変更すべきではありません。リクエストが一定時間以上失敗し続ける場合、通常は深刻なネットワーク問題があることを意味します。この場合、タイムアウトを延長する(成功の保証なしにプレイヤーをより長く待たせるだけ)のではなく、失敗を適切に処理する方が良いでしょう。例えば、プレイヤーをメインメニューに戻したり、接続エラーメッセージを表示したりすることで、プレイヤーは待機状態に陥ることなく、後で再試行できます。
HTTP リトライタイムアウトの処理
- Unreal Engine
- Unity
現在、Unreal Engine プロジェクトでは、HTTP リトライタイムアウトの処理は、ゲームが AGS Unreal Engine SDK を直接統合している場合にのみ可能です。ゲームが AGS OSS SDK を使用している場合、HTTP リトライ動作を制御することはできません。OSS SDK は、API リクエストが成功したかどうかを単純に報告するだけです。失敗した場合、エラーメッセージは通常、block-player-request-failed、unblock-player-request-failed、send-ds-ready-request-failed などの一般的なものになります。
HTTP API リトライがタイムアウトした場合、API レスポンスの FErrorHandler デリゲートの ErrorCode 値は ErrorCodes::NetworkError (14005) になります。例えば、プレイヤーの検索を実装する際、HTTP リトライタイムアウトは FErrorHandler デリゲートの ErrorCode 値をチェックすることで識別できます:
...
FApiClientPtr ApiClient = AccelByteOnlineSubsystemPtr->GetApiClient();
FString Query = FString("UsersDisplayName");
EAccelByteSearchType By = EAccelByteSearchType::DISPLAYNAME;
ApiClient->User.SearchUsers(Query,
By,
THandler<FPagedPublicUsersInfo>::CreateLambda([](const FPagedPublicUsersInfo & Result)
{
// SearchUsers が成功した場合の処理
}), FErrorHandler::CreateLambda([](int32 ErrorCode, const FString & ErrorMessage) {
// SearchUsers が失敗した場合の処理
UE_LOG(LogTemp, Warning, TEXT("Error SearchUsers. Code: %d, Message: %s"), ErrorCode, *ErrorMessage);
if(ErrorCode == static_cast<int32>(ErrorCodes::NetworkError))
{
// HTTP リトライタイムアウトを処理するソリューションを実装する。
}
})
);
...
HTTP API リトライがタイムアウトした場合、API レスポンスのコールバックの Error.Code 値は ErrorCode.NetworkError (14005) になります。例えば、プレイヤーの検索を実装する際、HTTP リトライタイムアウトは result コールバックの Error.Code 値をチェックすることで識別できます:
string query = "UsersDisplayName";
SearchType by = SearchType.DISPLAYNAME;
AccelByteSDK.GetClientRegistry().GetApi().GetUser().SearchUsers(query, by, result =>
{
if (!result.IsError)
{
// SearchUsers が成功した場合の処理
}
else
{
// SearchUsers が失敗した場合の処理
Debug.LogWarning($"Unable to Query Users Code: {result.Error.Code}, Message: {result.Error.Message}");
if(result.Error.Code.Equals(ErrorCode.NetworkError))
{
// HTTP リトライタイムアウトを処理するソリューションを実装する。
}
}
});
リクエストがここにリストされているエラーコードのいずれかに遭遇した場合、システムがリクエストのリトライを開始する際にエラーデリゲートはトリガーされません。エラーデリゲートは、リトライプロセスが終了した後にのみトリガーされます。これは、リトライ制限に達してタイムアウトした場合、または最終レスポンスコードがリストされたエラーコードのいずれでもない場合です。
Byte Wars UI 実装における HTTP エラーハンドリングの例
API 呼び出しの失敗を適切に処理することで、プレイヤー体験が向上します。各 Byte Wars 学習モジュールでは、ゲームの UI にエラーメッセージを表示することで API の失敗を管理しています。ただし、前述のとおり、Byte Wars は AGS OSS SDK を使用しているため、HTTP リトライタイムアウトエラーを識別することができません。これは、HTTP リトライタイムアウトは、AGS OSS SDK を使用せずに Unreal Engine SDK を直接使用している場合にのみ検出できるためです。その結果、Byte Wars のエラーメッセージは多くの場合一般的なものとなり、ゲームは失敗が HTTP リトライタイムアウトによるものか他の問題によるものかを判断できません。
以下は、失敗したリクエストを正しく処理する方法の例です。これらの例は、プレイヤーに役立つメッセージを表示する方法を示しています。
- Unreal Engine
- Unity