GS2-JobQueue

非同期ジョブキュー

GS2-JobQueue はゲームサーバー上で実行する処理を非同期に積み上げるためのジョブキュー機能を提供します。

ゲームの処理には、すぐに結果を返す必要のないものや、サーバー側で時間をかけて段階的に進めたいものがあります。 そのような処理を「ジョブ」としてキューに登録しておき、後からプレイヤーがアクセスしたタイミングや明示的なAPI呼び出しによって実行することができます。

主な用途

  • GS2-Script を非同期に実行するための実行基盤
  • 長時間処理を細かいステップに分割し、ステップごとにジョブとして登録して順次処理する
  • ログイン中に発生したリワード配布などをまとめてサーバー側でトランザクション発行・実行
  • 他マイクロサービスの完了通知ハンドラとして、後続処理を非同期に行う
graph LR
  Producer["ジョブ登録元<br/>(他のマイクロサービス / GS2-Script)"] --> Queue["GS2-JobQueue"]
  Queue --> Run["プレイヤーが Run を実行<br/>または 自動実行"]
  Run --> Script["GS2-Script"]
  Script -- 成功 --> Result["JobResult として記録"]
  Script -- 失敗 --> Retry{"最大試行回数<br/>に到達?"}
  Retry -- No --> Queue
  Retry -- Yes --> DeadLetter["DeadLetterJob として保管"]

自動実行モード

ネームスペースの設定で enableAutoRun を有効にすると、各マイクロサービスのAPI処理の最後にユーザーのキューに積まれているジョブを自動的に実行します。 プレイヤーがアプリを操作するだけで、サーバー側に積まれたジョブが順次消化されていきます。

enableAutoRun を無効にする場合は、クライアントから明示的に Run API を呼び出してジョブを実行する必要があります。

ジョブ結果

ジョブの実行結果は試行回数(tryNumber)ごとに JobResult として記録されます。 JobResult には GS2-Script の終了コード・実行ログ・結果ペイロードなどが含まれ、後から実行履歴を確認することができます。

通知設定

ネームスペースの設定で runNotificationpushNotification を構成しておくと、ジョブが実行されたとき、または新規にジョブがキューに積まれたときに GS2-Gateway を経由してクライアントへ通知できます。 この通知をフックに、クライアント側で残り情報を再取得するといった連携が可能です。

トランザクションアクション

GS2-JobQueue は他のマイクロサービスから完了通知の受け先として呼び出されることが多く、トランザクションアクションとしてジョブ登録を提供しています。

  • 入手アクション: ジョブをユーザーのキューに登録

たとえば GS2-Mission の完了報酬として GS2-JobQueue にジョブを積み、後でまとめて GS2-Script を実行するといった構成が可能です。

マスターデータ管理

GS2-JobQueue はマスターデータを持ちません。 振る舞いはネームスペースの設定でのみ制御します。

実装例

自分のキューに積まれているジョブを実行

enableAutoRun を無効にした場合や、明示的にジョブの消化を進めたい場合に呼び出します。 Run を呼び出すと、ジョブを1件取り出して GS2-Script を実行し、その結果を返します。 IsLastJobtrue であれば、これ以上消化すべきジョブが残っていないことを示します。

    var domain = gs2.JobQueue.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var result = await domain.RunAsync(
    );
    var isLastJob = domain.IsLastJob;
    var needRetry = result.NeedRetry;
    const auto Domain = Gs2->JobQueue->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    const auto Future = Domain->Run(
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError()) return false;
    const auto IsLastJob = Domain->IsLastJob;
    const auto NeedRetry = Future->GetTask().Result()->NeedRetry;

ジョブの実行結果を取得

特定のジョブの特定の試行回数の実行結果を取得します。

    var item = await gs2.JobQueue.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Job(
        jobName: "job-0001"
    ).JobResult(
        tryNumber: 1
    ).ModelAsync();
    const auto Domain = Gs2->JobQueue->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Job(
        "job-0001" // jobName
    )->JobResult(
        1 // tryNumber
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError()) return false;
    const auto Result = Future->GetTask().Result();

ジョブの状態を取得

キューに積まれているジョブの最新状態を取得します。 ジョブの現在の試行回数や登録された GS2-Script の情報などを確認できます。

    var item = await gs2.JobQueue.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Job(
        jobName: "job-0001"
    ).ModelAsync();
    const auto Future = Gs2->JobQueue->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Job(
        "job-0001" // jobName
    )->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError()) return false;
    const auto Result = Future->GetTask().Result();

詳細なリファレンス