LoginSignup
42
44

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-04-16

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とかうまくつかえないかなぁ。

42
44
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
42
44