Craft Counter を利用する
Craft Counter はCraft Functions内で利用できる高速なカウンターです。以下に示すユースケースのように秒間数10回以上のカウントアップ・ダウンリクエストが発生する場合に活用できます。
- 大規模なアンケート結果のリアルタイム集計
- 大規模なクーポン施策における払い出し枚数計測
Counter の構造
Craft Counterは key
とそれに紐づく value
からなるKey-Value Storeです。
key
- Counterのユニークなキーです。
- KARTEプロジェクト単位でユニークなキーです。
MODULES.counter
上はstring型の値として扱います。- マルチバイト文字は利用できません。
- Counterのユニークなキーです。
value
- キーに紐づくカウンターの値です。
MODULES.counter
上はnumber型の整数値として扱います。
各 key
の値には存在期間(TTL)が設定されます。TTLを過ぎたレコードは自動的に消去されます。
- デフォルトのTTLは86400秒(1日)です。
- TTLの最大値は2592000秒(30日)です。
- 値の設定が可能なメソッドでは引数に
secondsToExpire
を渡すことでTTLの設定ができます。
サンプルコード
Craft Counterへの値の書き込み、読み取り方法を示すためのサンプルコードです。
const LOG_LEVEL = "DEBUG";
export default async function (data, { MODULES }) { const { initLogger, counter } = MODULES; const logger = initLogger({ logLevel: LOG_LEVEL }); try { const setRes = await counter.set({ key: "test_key", value: 1000, secondsToExpire: 3600, }); logger.log("setRes", setRes); // 'OK'
await counter.increment({ key: "test_key" }); // 1001 const getRes = await counter.get({ keys: ["test_key"] }); logger.log("getRes", getRes); // [ 1001 ]
await counter.increment({ key: "test_key", changeAmount: 100 }); // 1101 const incrementRes = await counter.increment({ key: "test_key" }); // 1102 logger.log("incrementRes", incrementRes); // 1102
const incrementRes2 = await counter.increment({ key: "key_is_not_found_1", }); logger.log("incrementRes2", incrementRes2); // 1
const decrementRes = await counter.decrement({ key: "test_key" }); logger.log("decrementRes", decrementRes); // 1101
await counter.set({ key: "test_key", value: 0 }); // OK const decrementRes2 = await counter.decrement({ key: "test_key", changeAmount: 100, }); // -100 logger.log("decrementRes2", decrementRes2); // -100
const getRes2 = await counter.get({ keys: ["key_is_not_found_2"] }); // 0 logger.log("getRes2", getRes2); // [ 0 ]
return incrementRes; } catch (e) { logger.error(e); throw e; }}
メソッド
counter
モジュールで利用できるメソッドについて説明します。
set
/** * Craft Counterに数値を書き込む * @param {Object} param * @param {string} param.key 書き込むkey * @param {number} param.value 書き込むvalue * @param {number} [param.secondsToExpire] 値の有効期限(秒). デフォルトは86400(1日). 最大値は2592000(30日). * @returns {Promise<Object>} empty object */counter.set({ key, value, secondsToExpire })
Counterの特定の key
に value
で指定した数値を書き込みます。
secondsToExpire
でTTLが設定できます。- 省略した場合のデフォルト値は
86400
(1日) です。 - 設定できる最大値は
2592000
(30日) です。
- 省略した場合のデフォルト値は
get
/** * Craft Counterの数値を読む * @param {Object} param * @param {string[]} param.keys 書き込むkeyの配列 * @returns {Promise<number[]>} カウンターの値 */counter.get({ keys })
Counterの key
に紐づく数値を取得します。引数 keys
には読み込み対象の key
を配列として渡します。各 key
に紐づく数値からなる配列を返却します。Counterに存在しない key
を指定した場合、値は0として扱われます。
increment
/*** Craft Counterの数値をインクリメントする* @param {Object} param* @param {string} param.key インクリメントするkey* @param {number} [param.changeAmount] インクリメントする値. デフォルトは1* @param {number} [param.secondsToExpire] 値の有効期限(秒). 空の場合は現在の有効期限を維持する. 最大値は2592000(30日).* @returns {Promise<number>} インクリメント後の値*/counter.increment({ key, changeAmount, secondsToExpire })
Counterの key
に紐づく数値と changeAmount
の値を足し合わせます。返り値は足し合わせた後の値です。Craft Counterはこの処理をアトミックに行うため、同時に呼び出した場合も値は重複しません。
changeAmount
を省略した場合は1が加えられます。secondsToExpire
でTTLを再設定できます。省略した場合はTTLを更新しません。- 存在しない
key
も指定できます。その場合はkey
に紐づく値を0
とみなしてインクリメントし、1
を返却します。- 存在しない
key
を指定し、なおかつsecondsToExpire
を省略した場合、そのkey
のTTLは86400
(1日) となります。
- 存在しない
decrement
/** * Craft Counterの数値をデクリメントする * @param {Object} param * @param {string} param.key デクリメントするkey * @param {number} [param.changeAmount] デクリメントする値. デフォルトは1 * @param {number} [param.secondsToExpire] 値の有効期限(秒). 空の場合は現在の有効期限を維持する. 最大値は2592000(30日). * @returns {Promise<number>} デクリメント後の値 */counter.decrement({ key, secondsToExpire })
Counterの key
に紐づく数値から changeAmount
で指定した値を引き、引いた後の値を返却します。この処理はアトミックに行われるため、同時呼び出しの場合も値は重複しません。
changeAmount
を省略した場合は1が引かれます。secondsToExpire
でTTLを再設定できます。省略した場合はTTLを更新しません。- 存在しない
key
も指定できます。その場合はkey
に紐づく値を0
とみなしてデクリメントし、-1
を返却します。- 存在しない
key
を指定し、なおかつsecondsToExpire
を省略した場合、そのkey
のTTLは86400
(1日) となります。
- 存在しない
APIリファレンス
FAQ
Counterのレコードはどの単位で共有されますか?
- プロジェクト単位で1つのデータベースが共有されます。
- 複数のFunctionで同じデータが参照できます。
- Function単位でnamespaceを厳密に管理してください。
すでに存在する key に set した場合はどうなりますか?
- 既存のカウンターが上書きされます。
- TTLも上書きされます。(
secondsToExpire
もしくはデフォルトの86400秒)
秒間数十回を超える高いパフォーマンスが求められるケースに対応できますか?
- 要件によっては対応可能です。
- サポートや営業担当までご相談ください。