GASでまれに予期しないエラーが起こる
GoogleAppsScript(GAS)は無料で使えて、様々なことができてとても便利です。
ただ、無料で使わせてもらっておいてなんですが、ちょこちょこ予期しないエラーが発生してエラー対応で大変な思いをするときがあります。
たとえば
スプレッドシートの操作時に「スプレッドシートとの接続が切れました。」とエラーになったが、すぐに再実行してみると普通に成功する。。
みたいなことが起きます。
リトライすれば成功するのですが、GASには自動でリトライする処理は用意されていないので
以下のように自分で実装していきます。
・エラーになったら自動でリトライする
・トライ回数は自由に設定できる
・どんなエラーが起きたか分かるようログは出す
・指定回数実行してもエラーになる場合は、通知する
起きたり起きなかったりするエラーを再現
リトライ処理を実装するにあたって、テストしやすいように
起きたり起きなかったりするエラーを再現してみます。
タイムスタンプを取得して、そのタイムスタンプが偶数だったらエラーをスローさせます。
function main() {
// タイムスタンプ取得
const timestamp = Date.now();
console.log("タイムスタンプ: " + timestamp);
// タイムスタンプが偶数だったらエラー(起きたり起きなかったりするエラーの代わり)
if (timestamp % 2 === 0) {
throw new Error("テストエラー");
}
return "成功!!";
}
このように、タイムスタンプが偶数ならエラー、奇数なら正常終了します。
これをエラーが起きたり起きなかったりするmainの処理に見立てていきます。
GASの自動リトライ処理
GASの自動リトライ処理のコードは以下になります。
const tryCount = 3;
の数値を変えるだけで何回トライさせるかを変更することができます。
エラーの通知のさせ方など適宜変更していただければ。
function retryFunc() {
// トライ回数の設定
const tryCount = 3;
// 指定回数分ループ
for(let count=1; count < tryCount+1; count++){
try {
console.log("トライ回数: " + count);
// メインの処理を実行
const result = main();
// メインが成功したら、処理終了
console.log(result);
return;
// エラーが発生した場合
} catch (e) {
// トライ回数分リトライ
if (count < tryCount) {
console.warn(e.stack);
console.warn("予期せぬエラーが発生したためリトライします。");
continue;
}
// 以下、トライ回数実行しても成功しない場合エラー通知
console.error(e.stack);
console.error(tryCount + "回トライしても成功しませんでした。");
// ここに、メールやらSlack通知を入れて通知して処理終了
console.log("**** エラー通知の代わり ****");
}
}
}
1回で成功した場合
エラーなっていないのでcatch
に入らずそのままreturn
で処理が終了します。
1回目はエラー、2回目で成功した場合
1回目でエラーになりcatch
に入りif (count < tryCount)
がcountが 1
, tryCountが3
なのでif文に入りcontinue
されます。
2回目はエラーにならずcatch
に入らないためreturn
で処理が終了します。
「2回目もエラー、3回目で成功」も同様です。
3回ともエラー
1, 2回目でリトライされて、3回目もエラーになった場合はif (count < tryCount)
がcountが 3
, tryCountが3
となり、if文に入らずエラー通知されます。
コピペ用
ご自身のGASエディタにコピペできるようコード全体をのせます。
retryFunc()を実行して挙動の確認してみてください。
function retryFunc() {
// トライ回数の設定
const tryCount = 3;
// 指定回数分ループ
for(let count=1; count < tryCount+1; count++){
try {
console.log("トライ回数: " + count);
// メインの処理を実行
const result = main();
// メインが成功したら、処理終了
console.log(result);
return;
// エラーが発生した場合
} catch (e) {
// トライ回数分リトライ
if (count < tryCount) {
console.warn(e.stack);
console.warn("予期せぬエラーが発生したためリトライします。");
continue;
}
// 以下、トライ回数実行しても成功しない場合エラー通知
console.error(e.stack);
console.error(tryCount + "回トライしても成功しませんでした。");
// ここに、メールやらSlack通知を入れて通知して処理終了
console.log("**** エラー通知の代わり ****");
}
}
}
function main() {
// タイムスタンプ取得
const timestamp = Date.now();
console.log("タイムスタンプ: " + timestamp);
// タイムスタンプが偶数だったらエラー(起きたり起きなかったりするエラーの代わり)
if (timestamp % 2 === 0) {
throw new Error("テストエラー");
}
return "成功!!";
}