はじめに
GS2 ではサーバー処理に非同期処理を採用しているケースがあります。
トランザクション処理が代表的な例で、GS2-Showcase の商品購入APIを呼び出して応答を受け取った段階では購入処理は完了していることが保証されていません。
機能追加の背景
トランザクション処理のサーバーサイドでの自動実行を有効化している場合、APIを応答した後「対価」を消費し「報酬」を付与する処理がサーバーサイドで実行されます。
このサーバーサイドの処理の完了はサーバーからのプッシュ通知でハンドリングすることは可能ですが、
商品購入APIを呼び出した後、「対価」を消費し「報酬」を付与が正常に完了するまで待つためには、それなりにコードを記述する必要がありました。
追加された機能の詳細
トランザクション処理 API の戻り値が TransactionDomain型 に変更されました。
TransactionDomain には Wait / WaitAsync というAPIが用意されており、Wait であれば戻り値の IFuture を、WaitAsync であれば await で非同期処理の完了を待つことができるようになりました。
Wait / WaitAsync には bool all 引数があり、デフォルト値で false が渡されます。
ここに all を指定すると、トランザクション処理の結果、新たなトランザクション処理が実行された場合も、そのトランザクション処理が完了するまで待つことができます。
false を指定した場合、新たなトランザクション処理が実行された場合は戻り値に次の TransactionDomain オブジェクトが返ります。
全ての処理が完了した場合や、all に true を指定した場合は null が返ります。
注意事項
トランザクション処理は完了するまでの時間について保証がありません。
一部マイクロサービスに障害が発生した時に、トランザクション処理が正常に完了せず、await が返らない可能性があります。
必ずタイムアウトを併用するようにしてください。
なお便宜上「障害があって正常に完了しない」と表記しましたが、実際には障害発生時には自動的にトランザクション処理は正常に完了するまでリトライされます。
そのため障害復旧後に自動的に本来あるべき状態までデータが更新されます。
Unity での実装例
var transaction = await gs2.Showcase.Namespace( "showcase" ).Me( GameSession ).Showcase( "showcase-0001" ).DisplayItem( displayItem.DisplayItemId ).BuyAsync( ); await transaction.WaitAsync(); // BuyAsync で実行された非同期処理の完了を待つ