简体   繁体   English

超过最大执行时间

[英]Exceeded maximum execution time

Here's my code do:这是我的代码:

  1. Replicates a spreadsheet and dump it to a gdrive folder (no. of replications depends on the number of employees on my config file).复制电子表格并将其转储到 gdrive 文件夹(复制数量取决于我的配置文件中的员工数量)。 As of the moment, I have 800+ employees.截至目前,我有 800 多名员工。
  2. After replication, each spreadsheet in the gdrive folder are published to html.复制后,gdrive 文件夹中的每个电子表格都会发布到 html。 (i used a loop here) (我在这里使用了一个循环)
  3. Get the pubHTML link per spreadsheet and put it in my config file.获取每个电子表格的 pubHTML 链接并将其放入我的配置文件中。

I'm getting the exceeded maximum execution time when I'm on the step 3 part which is the to get the pubHTML and put it in my config file.当我在第 3 步部分获取 pubHTML 并将其放入我的配置文件时,我得到了超出的最大执行时间。

My code is working as expected.我的代码按预期工作。 I want to avoid the maximum limit of execution error.我想避免执行错误的最大限制。

  function replicateCards() {
  var ss = SpreadsheetApp.openById('configfile--xxxx');
  var copyCard = SpreadsheetApp.openById('replicateCard-xxxx');
  var getID = DriveApp.getFileById(copyCard.getId())
  var card = copyCard.getSheetByName("Card");
  var mastersheet = ss.getSheetByName("Mastersheet");
  var getLastRow = mastersheet.getLastRow();
  var destinationFolder = DriveApp.getFolderById('gdrivefolder-xxxx');
  var changeColorToGrayList = card.getRangeList(['C7', 'E7', 'G7', 'I7', 'K7', 'M7', 'O7', 'Q7',
                                                 'C9', 'E9', 'G9', 'I9', 'K9', 'M9', 'O9', 'Q9',
                                                 'C11', 'E11', 'G11', 'I11', 'K11', 'M11', 'O11', 'Q11']);
  var setValueToZero = card.getRangeList(['C8', 'E8', 'G8', 'I8', 'K8', 'M8', 'O8', 'Q8',
                                          'C10', 'E10', 'G10', 'I10', 'K10', 'M10', 'O10', 'Q10',
                                          'C12', 'E12', 'G12', 'I12', 'K12', 'M12', 'O12', 'Q12']);
  for (i = 1; i < getLastRow; i++) {
    var badgeStatus = mastersheet.getRange(i + 1, 5).getValue();
    if (badgeStatus == "") {
      var employeeNumber = mastersheet.getRange(i + 1, 1).getValue();
      var employeeName = mastersheet.getRange(i + 1, 2).getValue();
      copyCard.getRange("H3").setValue(employeeNumber);
      copyCard.getRange("C3").setValue(employeeName);
      SpreadsheetApp.flush();
      if(mastersheet.getRange(1 + i, 5).getValue() != "completed"){
        getID.makeCopy(employeeNumber, destinationFolder);
        mastersheet.getRange(1 + i, 5).setValue("completed");
      }
      //          Logger.log(i);
      SpreadsheetApp.flush();

    }
  }
  var files = DriveApp.getFolderById(SpreadsheetApp.openById("configFile-xxxx").getSheetByName("Config Sheet").getRange("B1").getValue()).getFiles();
  //var fileIter = 1;
  var employeeNumbers = mastersheet.getRange("A2:A").getValues();
  var employeeNumbersTrunc = []
  for(var i = 0; i < employeeNumbers.length; i++){
    if(employeeNumbers[i][0] != "")
      employeeNumbersTrunc.push("" + employeeNumbers[i][0]);
  }
  Logger.log(employeeNumbersTrunc);

  while (files.hasNext()) {
    var file = files.next();
    /*var Found = false;
    for (var j = 0; j < ; fileIter++) {
      if (employeeNumber2[j][0] == file.getName()) {
        Found = true;
      }
    }//*/
    if (employeeNumbersTrunc.indexOf(file.getName())==-1) {
      continue;
    }else if(mastersheet.getRange(2 + (employeeNumbersTrunc.indexOf(file.getName())), 9).getValue() != ""){
      continue;
    }
    try {
      var fileId = file.getId();
      var fileName = file.getName();
      var revisions = Drive.Revisions.list(fileId);
      var lastRevisionId = revisions.items[revisions.items.length - 1].id;
      // get the resource and set the publish parameters
      var resource = Drive.Revisions.get(fileId, lastRevisionId);
      //       Logger.log(resource);
      resource.published = true;
      resource.publishAuto = true;
      resource.publishedOutsideDomain = true;
      // publish to the web
      Drive.Revisions.update(resource, fileId, lastRevisionId);
      SpreadsheetApp.flush();
      var openByID = SpreadsheetApp.openById(fileId);
      SpreadsheetApp.flush();
      var googleDriveSheet = openByID.getUrl().replace("edit", "pubhtml"); // or replace("edit", "pub");
      SpreadsheetApp.flush();
      Logger.log(file.getName());
      Logger.log(employeeNumbersTrunc.indexOf(file.getName()));
      mastersheet.getRange(2 + (employeeNumbersTrunc.indexOf(file.getName())), 9).setValue(googleDriveSheet);
      SpreadsheetApp.flush();
    } catch (err) {
      Logger.log(err);
    }
  }
}

Run the code one time only without the exceeded maximum execution time error.只运行一次代码,不会出现超出最大执行时间的错误。 Any suggestions?有什么建议么?

The code below is modified from what I've used before.下面的代码是根据我以前使用的代码修改的。 An approach like this allows you to fully execute a batch that alone cannot be done within the execution time limit .像这样的方法允许您完全执行一个单独无法在执行时间限制内完成的批处理。 By knowing how long a single operation in the batch takes, you can save your progress in the Properties before reaching that limit and programmatically create a trigger to resume processing.通过了解批处理中的单个操作需要多长时间,您可以在达到该限制之前将进度保存在属性中,并以编程方式创建触发器以恢复处理。

You will need to do a few things to make it work:您需要做一些事情才能使其工作:

  1. You need to modify my getEmployees_() function to accurately get the employees from your config file.您需要修改我的getEmployees_() function 以准确地从您的配置文件中获取员工。
  2. As I mentioned in my comment, you need to refactor your code so that you can execute the replication for a single employee.正如我在评论中提到的,您需要重构代码,以便可以为单个员工执行复制。 That code should go in my replicateForEmployee_() function.该代码应在我的replicateForEmployee_() function 中为 go。
  3. Run the determineTimes() function to see how long getting employees & file replication takes.运行determineTimes() function 以查看获取员工和文件复制需要多长时间。
  4. Insert the results of determineTimes() in the replicate() function.replicate() function 中插入determineTimes()的结果。

The output of determineTimes() will be visible in the Executions page (View > Executions). determineTimes()的 output 将在“执行”页面(查看 > 执行)中可见。 Expand the execution row and you will see the durations as pictured.展开执行行,您将看到如图所示的持续时间。

执行日志

/**
 * Get all of the employees in the sheet. Assumes row in the sheet is one employee. Adjust the range as needed.
 * @returns {Object[][]}
 */
function getEmployees_() {
  var source = SpreadsheetApp.openById("configfile--xxxx");
  var sheet = source.getSheetByName("Mastersheet");
  return sheet.getRange(1, 1, sheet.getLastRow(), sheet.getLastColumn()).getValues();
}

/**
 * Refactor your current code so that this function will replicate all necessary files for a single
 * employee. The function will be called for every single employee.
 * @param {Object[]} employee - The row representing the employee in your config file
 */
function replicateForEmployee_(employee) {
  // Execute your replication process for a SINGLE employee here
}

/**
 * Run this, and then examine your script executions (View > Executions) to see how long each
 * function takes. The resulting durations should replace the corresponding values in the replicate()
 * function (I would recommend rounding up, so 458 --> 500ms).
 */
function determineTimes() {
  console.time("timeToGetEmployees");
  var employees = getEmployees_(); // Get all of the employees
  console.timeEnd("timeToGetEmployees");

  console.time("replicationDuration");
  replicateForEmployee_(employees[0]); // Execute replication once
  console.timeEnd("replicationDuration");
}

/**
 * Replicates the files. When approaching the time limit, will save location and set a trigger to
 * continue from stopping point. Emails user upon completion.
 * @param {Boolean} isFromTrigger
 * @returns {undefined}
 */
function replicate(isFromTrigger) {
  var employees = getEmployees(); // Get all of the employees
  var timeToGetEmployees = 1000; // Assume 1 second to execute getEmployees()
  var replicationDuration = 500; // Number of milliseconds it takes to execute replication for one employee.
  var maxExecutionTime = 360000 - timeToGetEmployees; // 6 mins - time already used to get employees

  var continueFrom = 0; // If first execution, will be zero. Otherwise, get the index to start from.
  if (isFromTrigger === true) {
    continueFrom = parseInt(PropertiesService.getScriptProperties().getProperty("continueFrom"), 10);
  }
  var lapsedTime = 0; // ESTIMATED amount of time that has lapsed since the replication started

  for (var i = continueFrom; i < employees.length; i++) {
    // Replicate files for the employee
    replicateForEmployee_(employees[i]);

    // Checks how much time you have left
    lapsedTime += replicationDuration;
    if (lapsedTime >= (maxExecutionTime - replicationDuration)) { // warn just before timing out
      PropertiesService.getScriptProperties().setProperty("continueFrom", i + 1); // save the last iterator value + 1
      createAfterTrigger("replicateFromTrigger", 60000); // Start again in one minute
      console.info("About to time out. Last iterator: " + i);
      return;
    }
  }

  deleteAllTriggers(); // Cleanup any lingering triggers
  PropertiesService.getScriptProperties().deleteProperty("continueFrom"); // Clean up properties

  // Send completion email
  MailApp.sendEmail(Session.getEffectiveUser().getEmail(), "Replication Complete", "");
}

/**
 * Should ONLY ever be called from a clock trigger.
 * @returns {undefined}
 */
function replicateFromTrigger() {
  replicate(true);
}

/**
 * Create a new trigger to execute the specified function after a certain amount of time.
 * @param {String} functionName - The name of the function to execute
 * @param {Number} milliseconds - The duration (in milliseconds) after the current time when the trigger should run
 * @returns {undefined}
 */
function createAfterTrigger(functionName, milliseconds) {
  ScriptApp.newTrigger(functionName)
  .timeBased()
  .after(milliseconds)
  .create();
}

/**
 * Deletes all triggers in the current project.
 * @returns {undefined}
 */
function deleteAllTriggers() {
  var triggers = ScriptApp.getProjectTriggers();
  for (var i = 0; i < triggers.length; i++) {
    ScriptApp.deleteTrigger(triggers[i]);
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM