During the Warring States period in the 16th century, the life expectancy of the Japanese was less than 50 years. Today, however, their average life expectancy is over 84 years(the best in the world)! This may be related to peace, medical advances, and better nutrition.

By the way, wouldn’t you like your Google Apps Script runs to live longer too? This is because, typically, its feasibility time is only six minutes. If you try to go any further, you will see the following error message:

Exceeded maximum execution time!!

I faced this problem too, so I created an original class to solve it, and when I published it, the response was unexpectedly positive. So in this article, I would like to focus on how you can make your scripts executable for a longer period of time.

What is the LongRun class?

LongRun is a class that uses Google’s Properties Service and time-driven triggers to enable processes to run for more than 6 minutes. You can find out more about how it works here:

Also, the source for this class is available on Github.

Test Script

Now I will show you how the LongRun class can be used to make a script executable for an extended period of time. The following is a typical file processing code. This code retrieves files in Google Drive one by one and outputs the information to a spreadsheet.

function myFunction() {
  const targetFolderId = 'YOUR_FOLDER_ID';
  const outputFileName = 'FileInfo';

  // create output file
  let spreadsheet = SpreadsheetApp.create(outputFileName);
  let sheet = spreadsheet.getActiveSheet();

  // output header
  sheet.appendRow( ['name', 'link'] );   

  // get all files 
  let folder = DriveApp.getFolderById(targetFolderId);
  let files = folder.getFiles();
  while (files.hasNext()) {
    let file = files.next();
    let name = file.getName();
    let link = file.getUrl();

    // append file info
    sheet.appendRow( [name, link] );   
    // output log
    console.log(name + ':' + link);
  }
}

When you run this script, you will get the following results.

Information for 3 files

With three files, the process ends immediately. However, if there are tens of thousands of files, the 6-minute limit may be exceeded.
I will explain how it can be remade to run for a longer period of time in the sections that follow. 👍

Use the LongRun class and remake your script to run for a longer period of time

1. Integrate LongRun class
  1. Open Apps Script Editor.
  2. Add a new Script file named LongRun.gs.
  3. Copy the contents of this file and paste it into LongRun.gs you created.

* You can see the GitHub repository here.

Integrate LongRun class
2. Split the function

In this article, I will show an easier way to use the LongRun class: using the executeLongRun function.

To do so, the target function must be split into at least two parts. The startup part and the main processing part. The startup part sets various parameters and executes the executeLongRun function. The main processing part, on the other hand, describes the processing for each unit.

Let’s look at the code 👀

/**
 * the startup part
 */
function myFunction() {
  const targetFolderId = 'YOUR_FOLDER_ID';
  const outputFileName = 'FileInfo';

  // create output file
  let spreadsheet = SpreadsheetApp.create(outputFileName);
  let sheet = spreadsheet.getActiveSheet();

  // output header
  sheet.appendRow( ['name', 'link'] );   

  // get all files to get file count
  let folder = DriveApp.getFolderById(targetFolderId);
  let files = folder.getFiles();
  let count = 0;
  while (files.hasNext()) {
    files.next();
    count++;

    // --- move to main() ---
    // let file = files.next();
    // let name = file.getName();
    // let link = file.getUrl();
    // // append file info
    // sheet.appendRow( [name, link] );   
    // -----------------------
  } 

  // run the long-run process
  let params = [targetFolderId, spreadsheet.getId()];
  executeLongRun("main", count, params);
}

/**
 * the main processing part
 * @param {number} index - index of processing target.
 * @param {Array} params - 0: targetFolderId, 1: outputFileId
 */
function main(index, params) {

  // This is for a long-run test.
  // LongRun.instance.setMaxExecutionSeconds(1);
  // Utilities.sleep(1000);

  const targetFolderId = params[0];
  const outputFileId = params[1];

  // get output file
  let spreadsheet = SpreadsheetApp.openById(outputFileId);
  let sheet = spreadsheet.getActiveSheet();

  // get all files 
  let folder = DriveApp.getFolderById(targetFolderId);
  let files = folder.getFiles();

  let i = 0;
  while (files.hasNext()) {
    let file = files.next();
    // process only the target data.
    if ( i === index ){
      let name = file.getName();
      let link = file.getUrl();
      // append file info
      sheet.appendRow( [name, link] ); 
      // output log
      console.log(name + ':' + link);
      break;
    }
    i++;
  }
}

First, the myFunction function only creates an output file and counts the number of files to be processed, and calls the executeLongRun function.
At this time, the ID of the output file is passed as one of the parameters so that the main function can receive it.
In this way, even if the processing is interrupted by a long run, the main function can retrieve the ID of the output file from the parameter when it resumes.

Next, the main function then executes the operation only on the file to be processed. ( if ( i === index ){ … )
By dividing the processing time into short segments in this way, processing is interrupted before it exceeds 6 minutes and resumed again.

Although some parts may appear redundant, the startup and main parts are appropriately separated to enable long-time execution.

*In addition to the main process, initialization and termination processes can also be defined. For details, please refer to the repository.

Execution & Confirmation

Let’s execute myFunction. If there are only a few files in the folder, it will end quickly, as in the following results.

Execution log

But if the number of files is very large, or if the maximum execution time is reduced for testing purposes, the process will be interrupted with the following log output.

The process has been suspended

But don’t worry❗️ The process is registered in the trigger so that it can be restarted next time. You can check it in the Triggers section of the Apps Script Editor.

The next process is registered in the trigger

You will find the log of the entire process in the Executions section. 👍

All processes executed

Conclusion

To enable existing scripts to run for extended periods of time, a little creativity is required.
But if you can make this powerful Google Apps Script run for a long time, it will open up all kinds of possibilities for building your business system.
I hope you find this article useful. 😊


4 Responses

  1. i am newbie in appscript. I am interested in applying this method to copy a sheet to another file. but confused how to separate getrange and setvalue scripts into 2 functions so they don’t get request time out

Leave a Reply

Your email address will not be published.