Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
35
Help us understand the problem. What is going on with this article?
@s_maeda_fukui

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

More than 3 years have 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とかうまくつかえないかなぁ。

35
Help us understand the problem. What is going on with this article?
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
s_maeda_fukui
目指せ!カイゼンマスター!(マーケティング・エンジニア営業企画もどき) 高専・電子情報卒→大学文転→CRMマーケター(スクラムマスター取れた。)

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
35
Help us understand the problem. What is going on with this article?