コンテンツにスキップ

Craft Counter を利用する

Craft Counter はCraft Functions内で利用できる高速なカウンターです。以下に示すユースケースのように秒間数10回以上のカウントアップ・ダウンリクエストが発生する場合に活用できます。

  • 大規模なアンケート結果のリアルタイム集計
  • 大規模なクーポン施策における払い出し枚数計測

Counter の構造

Craft Counterは key とそれに紐づく value からなるKey-Value Storeです。

  • key
    • Counterのユニークなキーです。
      • KARTEプロジェクト単位でユニークなキーです。
    • MODULES.counter 上はstring型の値として扱います。
    • マルチバイト文字は利用できません。
  • 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の特定の keyvalue で指定した数値を書き込みます。

  • 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リファレンス

Craft Counter

FAQ

Counterのレコードはどの単位で共有されますか?

  • プロジェクト単位で1つのデータベースが共有されます。
  • 複数のFunctionで同じデータが参照できます。
    • Function単位でnamespaceを厳密に管理してください。

すでに存在する key に set した場合はどうなりますか?

  • 既存のカウンターが上書きされます。
  • TTLも上書きされます。(secondsToExpire もしくはデフォルトの86400秒)

秒間数十回を超える高いパフォーマンスが求められるケースに対応できますか?

  • 要件によっては対応可能です。
  • サポートや営業担当までご相談ください。