GS2-Lottery トランザクションアクション
アクションの組み合わせと同時実行
すべてのサービスに共通する前提は トランザクションアクションの組み合わせ にまとめています。先にそちらを読んでください。この節の残りは GS2-Lottery 固有の内容です。
GS2-Lottery がトランザクションに指定できるアクションは 2 つです。抽選は 1 つずつ、当選した景品を算出してそれを自身のトランザクションとして発行します。10 連の抽選なら 10 個の内側のトランザクションになります。GS2-Lottery を使ううえで最も注意が必要なのはこの点で、下記「景品が配るもの」にまとめています。
GS2-Lottery 自身の中で何を触るかは景品テーブルの種類によります。通常の景品テーブルはユーザーごとの状態を持ちませんが、箱の景品テーブルはネームスペース・ユーザー・景品テーブルの組で決まる箱を持ちます。
| 操作 | 同じ行を重ねたとき | 入れ子越し | 別の対象になる境界 |
|---|---|---|---|
抽選DrawByUserId | 抽選モデルと config が同じなら統合され、抽選回数が合算される。同じ箱に対する config が違う抽選は失敗する | 箱の景品テーブルなら失敗する。通常の景品テーブルなら衝突しない | ネームスペース・ユーザー・抽選モデル・config |
箱のリセットResetBoxByUserId | 1 件に統合される | 失敗する | ネームスペース・ユーザー・景品テーブル |
通常の景品テーブルはユーザーごとの状態を持たないため、1 つのトランザクションで何度抽選してもここでは衝突しません。抽選が配るものは別の話で、下記のとおりです。
抽選とリセットは行が違い、同じ箱に対しては境界が同じなので、1 つのトランザクションに入れることはできません。箱をリセットしてから抽選する流れも、衝突の問題を別にして成立しません。抽選はトランザクション開始時点の状態から行われるため、リセットが見えていないからです。
景品が配るもの
抽選の景品はそれぞれ内側のトランザクションとして発行されるため、それらが属するサービスの制限がそのまま当てはまり、下記「入れ子になったトランザクションに注意」も当てはまります。抽選が 2 回あれば内側のトランザクションも 2 つで、それらは互いにも統合されません。
GS2-Lottery で最も注意すべきなのがこの点です。10 連の抽選や、1 つのトランザクションでの複数の抽選では、同じアイテム・同じ通貨・同じステータスを配る景品が 2 つ出ることが容易に起こります。それが許されるかどうかを決めるのは GS2-Lottery ではなく、景品が属するサービスです。それらのサービスの入れ子に関する記述を確認してください。
なお景品ごとの抽選上限に達している景品は当選せず、代わりに別の景品が抽選されます。上限に達してもトランザクションが失敗するわけではありません。
入れ子になったトランザクションに注意
内側から抽選された箱と、外側からリセットされた同じ箱が衝突して、トランザクションが失敗します。
制限を回避したい場合
抽選も箱のリセットも入手アクションなので、「箱からの抽選とリセットの同居」「config が違う抽選の複数指定」はどちらも acquireActionUseJobQueue を有効にすれば解消できます。enableAtomicCommit を無効にすると、別々の抽選の景品も 1 回の書き込みに集まらなくなります。
同時実行とリトライ
通常の景品テーブルからの抽選は、GS2-Lottery 自身の中では同時実行のリクエストとコンフリクトしません。コンフリクトするかどうかは、景品が配るものによって決まります。
箱からの抽選と箱のリセットはどちらも箱を書き換えるため、同時に実行すると後から確定した側がコンフリクト (409) になります。これが同じ景品を箱から二重に取り出さないための仕組みです。リトライすると最新の箱の状態で判定し直されます。
Acquire Action
入手アクション
Gs2Lottery:DrawByUserId
ユーザーIDを指定して抽選を実行
抽選モデルの設定に基づいて、指定されたユーザーの抽選を実行します。
抽選は2つの方式をサポートします:排出確率テーブルモード(事前定義された確率テーブルを使用)とスクリプトモード(GS2-Script で景品を決定)。
ボックス抽選モードでは、排出された景品はボックスから削除され再度排出されません。ボックスが空の場合は Empty エラーが返されます。
排出された景品はトランザクションとして発行されます。
数量指定可能なアクション:はい
反転可能なアクション:いいえ
| 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128文字 | ネームスペース名 | ||
| lotteryName | string | ✓ | ~ 128文字 | 抽選モデル名 抽選モデル固有の名前。英数字および -(ハイフン) _(アンダースコア) .(ピリオド)で指定します。 | ||
| userId | string | ✓ | ~ 128文字 | ユーザーID#{userId} と設定することでログイン中のユーザーIDに置換されます。 | ||
| count | int | ✓ | 1 ~ 1000 | 抽選回数 | ||
| config | List<Config> | [] | 0 ~ 1000 items | トランザクションのプレースホルダに適用する設定値 | ||
| timeOffsetToken | string | ~ 1024文字 | タイムオフセットトークン |
{
"action": "Gs2Lottery:DrawByUserId",
"request": {
"namespaceName": "[string]ネームスペース名",
"lotteryName": "[string]抽選モデル名",
"userId": "[string]ユーザーID",
"count": "[int]抽選回数",
"config": [
{
"key": "[string]名前",
"value": "[string]値"
}
],
"timeOffsetToken": "[string]タイムオフセットトークン"
}
}action: Gs2Lottery:DrawByUserId
request:
namespaceName: "[string]ネームスペース名"
lotteryName: "[string]抽選モデル名"
userId: "[string]ユーザーID"
count: "[int]抽選回数"
config:
- key: "[string]名前"
value: "[string]値"
timeOffsetToken: "[string]タイムオフセットトークン"transaction.service("lottery").acquire.draw_by_user_id({
namespaceName="[string]ネームスペース名",
lotteryName="[string]抽選モデル名",
userId="[string]ユーザーID",
count="[int]抽選回数",
config={
{
key="[string]名前",
value="[string]値"
}
},
timeOffsetToken="[string]タイムオフセットトークン",
})Gs2Lottery:ResetBoxByUserId
ユーザーIDを指定してボックスをリセット
指定されたユーザーのボックスを初期状態にリセットし、排出済みのすべての景品をボックスに戻します。
数量指定可能なアクション:いいえ
反転可能なアクション:いいえ
| 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128文字 | ネームスペース名 ネームスペース固有の名前。英数字および -(ハイフン) _(アンダースコア) .(ピリオド)で指定します。 | ||
| prizeTableName | string | ✓ | ~ 128文字 | 排出確率テーブル名 | ||
| userId | string | ✓ | ~ 128文字 | ユーザーID#{userId} と設定することでログイン中のユーザーIDに置換されます。 | ||
| timeOffsetToken | string | ~ 1024文字 | タイムオフセットトークン |
{
"action": "Gs2Lottery:ResetBoxByUserId",
"request": {
"namespaceName": "[string]ネームスペース名",
"prizeTableName": "[string]排出確率テーブル名",
"userId": "[string]ユーザーID",
"timeOffsetToken": "[string]タイムオフセットトークン"
}
}action: Gs2Lottery:ResetBoxByUserId
request:
namespaceName: "[string]ネームスペース名"
prizeTableName: "[string]排出確率テーブル名"
userId: "[string]ユーザーID"
timeOffsetToken: "[string]タイムオフセットトークン"transaction.service("lottery").acquire.reset_box_by_user_id({
namespaceName="[string]ネームスペース名",
prizeTableName="[string]排出確率テーブル名",
userId="[string]ユーザーID",
timeOffsetToken="[string]タイムオフセットトークン",
})