Help us understand the problem. What is going on with this article?

[GAS]実行時間6分の壁を越えよう(不死鳥関数編)

More than 1 year has passed since last update.

Google Apps Scriptの限界を越えよう

GASでは、実行時間6分の壁があります。
でっかい処理を行ったときに、タイムアウトするというやつですね。
本稿では、タイムアウトする前にいったん処理を中止して、トリガーセットで再度実行させるという方式で立ち向かってみます。

と、その前に

こういうやり方もありますよ、とお見せする前に。

  • 余計なAPI呼び出ししてないですか?
    • 無意味なデータ読み書き
  • 冗長なAPI呼び出ししてないですか?
    • データ読み書きがまとまっていない
  • それ、まじでGASでやる必要ありますか?

データの読み書きにフォーカスしているのは、非エンジニアにとってスプレッドシートを触る機会が圧倒的に多く、かつGASの中でシートデータの読み書きは 圧倒的に時間がかかる からです。
正直、計算とかはすぐ終わります。数秒です。
読み書きはデータの大きさによっては数分かかります。

不死鳥のように蘇らせよう

道具

実行イメージ

  1. スクリプトのプロパティから必要な値を引っ張ってくる
  2. 関数実行開始時間を取得
  3. ループ
    1. 現在時刻の取得
    2. difference = { 現在時刻 - 実行開始時刻 }
    3. ◯分経過しているか
      • している
        スクリプトプロパティの更新を行う
        次回実行のためのトリガーの設定
      • していない 処理を行う
  4. ループ後処理(必要なら)
  5. スクリプトプロパティの初期化
  6. トリガーの削除(しないと永遠に回り続けるぞ?)

スクリプト例

/*
* GAS5分実行を越える!!
* スクリプトプロパティを活用
*/
function phoenix(){
  var properties
    = PropertiesService.getScriptProperties();
  // 例はint
  var prop
    = parseInt( properties.getProperty("<name_of_property>") );

  // 関数実行時点の時刻取得
  var start_time = new Date();

  for( i ){
    // 現在時刻を取得する
    var current_time = new Date();
    // 実行時間取得
    var difference
      = parseInt( (current_time.getTime() - start_time.getTime()) / (1000 * 60) );

    //4分を超えていたら中断処理
    if(difference >= 4){
      /* 値の書き込みとか必要ならやる */

      // スクリプトプロパティの更新
      properties.setProperty("<name_of_property>",i);

      // ここはもうちょっと利口なやり方がありそう。
      ScriptApp
      .newTrigger("phoenix")
      .timeBased()
      .everyMinutes(5)
      .create();

      return ;
    }else{
      /* 通常処理 */
    }//if_escape
  }//ループ処理

  // スクリプトプロパティの初期化
  properties.setProperty("<name_of_property>",<initial_value>);

  //特定関数のトリガーのみ削除
  delete_specific_triggers("phoenix");

  return ;

}//func_phoenix

// 特定関数のトリガーを全て削除
function delete_specific_triggers( name_function ){
  var all_triggers = ScriptApp.getProjectTriggers();

  for( var i = 0; i < all_triggers.length; ++i ){
    if( all_triggers[i].getHandlerFunction() == name_function )
      ScriptApp.deleteTrigger(all_triggers[i]);
  }//for_i
}//func_deleteSpecificTriggers

備考

もっと利口なやり方があると思われますので、編集リクエストお待ちしております。
Class ClockTriggerBuilder - afterとかうまくつかえないかなぁ。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした