キャッシュへ入れた値が取れなくなっても、元データが消えたとは限りません。GASのCacheServiceは、何度も計算する値などを一時的に再利用するための仕組みです。受付番号や処理の完了記録のように、失うと困る唯一の保存先には向きません。
公式資料では、保存時に指定した有効期間は目安で、期限より早く削除される場合があると説明されています。取得できなければ元データから作り直せる設計にして、キャッシュがあることを処理の前提にしないようにします。
nullなら元データへ戻る
cache.get(key)の戻り値は文字列かnullです。nullはそのキーの値が見つからない状態で、業務上の集計が0という意味ではありません。空の文字列や数字の0とも区別します。
今回の例は表示用の小さな集計結果をキャッシュします。JSONが壊れている場合や、必要な項目がそろっていない場合も、保存値をそのまま信用せず再計算へ戻します。元データを取得できなければ、0でごまかさずそのエラーを返します。
キャッシュの戻り値と有効期間はCacheの公式資料、共有範囲はCacheServiceで確認できます。
値がなくても動く読み取り関数
読み取り用関数を引数に渡し、キャッシュを使わない場合の動きを分けます。例のキーにv1を入れているのは、計算内容を変えたときに古い形式を使い続けないためです。
function loadPracticeSummary(cache, calculate) {
const key = 'practice-summary-v1';
const raw = cache.get(key);
if (raw !== null) {
try {
const value = JSON.parse(raw);
if (value && Number.isSafeInteger(value.count) && value.count >= 0 &&
typeof value.total === 'number' && Number.isFinite(value.total)) {
return {value: value, fromCache: true};
}
} catch (error) {
// 不正な一時データは使わず、元の計算へ進みます。
}
}
const value = calculate();
if (!value || !Number.isSafeInteger(value.count) || value.count < 0 ||
typeof value.total !== 'number' || !Number.isFinite(value.total)) {
throw new Error('再計算の結果を確認してください');
}
cache.put(key, JSON.stringify(value), 60);
return {value: value, fromCache: false};
}
function previewCachedSummary() {
const cache = CacheService.getUserCache();
const result = loadPracticeSummary(cache, function () {
const amounts = [100, 200]; // 架空の練習データです。
return {count: amounts.length, total: amounts.reduce((a, b) => a + b, 0)};
});
console.log(JSON.stringify(result));
}
キャッシュがなければcount:2,total:300,fromCache:falseが想定されます。次に値が残っている間の呼び出しではfromCache:trueになります。60秒は練習用の指定で、その時間いっぱい保存されることを保証するものではありません。
利用者の範囲も選ぶ
getScriptCacheはスクリプトの利用者で共有するキャッシュです。一方、getUserCacheは現在の利用者とスクリプトに対応します。利用者ごとに内容が違う結果を、共通のキーでスクリプトキャッシュへ入れると、別の人へ同じ結果を返す設計になり得ます。
この例は利用者側のキャッシュを選んでいます。ただし、実行する利用者が誰になるかは実行方法に左右されます。Webアプリの実行者設定も確認し、キャッシュの種類だけでアクセス権限を代用しないでください。
データが更新された直後でも、キャッシュが残れば古い計算結果を返します。表示の古さを許容する時間を決めるか、元データのバージョンをキーへ含めるなど、更新との対応を考えます。正確な受付状態を判断する用途では、元の保存先を読みます。
永続的な設定とは分ける
APIの設定値などを保存する方法はPropertiesServiceで扱っています。キャッシュはなくても作り直せる情報、正式なデータは失わず管理する保存先という役割を分けます。
このコードはキャッシュサービス自体の障害までは吸収しません。取得・保存がエラーになれば処理は止まるので、必要なら障害時に元の計算へ進むかを別に設計します。ローカルでは代用キャッシュのヒット、未存在、不正JSON、不正な型、再計算失敗を確認しました。Google上の保持時間は未計測です。処理の分離はGASコードの整理も参考になります。
