我已經創建了我的第一個 Google Workspace 插件,我已成功部署到相關域,但由于此錯誤仍在處理它。
沒有錯誤,在功能上它(曾經)運行良好,但是,我現在不斷收到“超過最大執行時間”錯誤。
這個錯誤是令人沮喪的斷斷續續的,但它最近開始出現大約 90% 以上的時間,盡管之前幾周都沒有發生過。恢復到我的代碼的以前版本并沒有解決問題。
大多數(如果不是全部)關于此錯誤的現有答案都假定腳本確實超過了腳本的時間限制(6 分鐘或 30 分鐘)。
需要明確的是 - 這不是這里發生的事情。該腳本不會在接近允許的最大時間的任何地方運行(據我所知)。在給出錯誤之前它實際上運行了大約 45 秒。
它可能以某種方式在后臺運行并導致合法的超時錯誤,但我需要弄清楚是否是這種情況以及錯誤的原因,然后修復它。
我已經聯系了谷歌,但不幸的是,他們的相關支持人員非常了解這一點并且可以提供幫助。
在針對此錯誤的 Cloud Logging 中,我看到(混淆的 id):
{
"insertId": "28z8v2anf1xq6",
"jsonPayload": {
"context": {
"reportLocation": {
"filePath": "[unknown file]",
"functionName": "[unknown function]"
}
},
"message": "Exceeded maximum execution time",
"serviceContext": {
"service": "AKfycbx-SO5mXBNoe2leEH4wrj02t9fZZwkq5BQlJPuBaNM"
}
},
"resource": {
"type": "app_script_function",
"labels": {
"function_name": "fileMakerPro",
"invocation_type": "unknown",
"project_id": "order-management-713317"
}
},
"timestamp": "2022-03-10T10:09:58.827Z",
"severity": "ERROR",
"labels": {
"script.googleapis.com/process_id": "fIxbX5X5IjrIqLLK-XQgJiJV0U9vQMEAEA1GOxTqw-XzqsaVlKTNK2UcymM7feuXp-qZLshvBUg61TS6u28l_v6szoAq8QBBOvGudISVj0yceQXPKpIHO6HJ2G-uxuqy4xcnv-NzDfBTMbJH7VmK_AjZd6a5KVA-LnhtOE_28mCn_zTpI5AC3-BhX_lcCC1p-3QsMX6blhMZSYgVTTo1T_Z9SovufUWinpJieIbio-L8wzQPkjLYM2l9s5RHGuKMcT3LbvUO7fFS4DV1z_xfaR_nU1LqeayAk1aouGSXc",
"script.googleapis.com/user_key": "wPo7ZL4DSIqpPrZfeqo7E7yAArA430YCNnzbVYhyuVlR6nKybMkISeaDZoigRDx0gAJXIjF49EoL",
"script.googleapis.com/deployment_id": "wkq5BQlJPcbx-SO5mEHAKfywrj02t9fZZ4uBXBNoe2leaNM",
"script.googleapis.com/project_key": "Xf9t90MIwJJbMnu2Z9hQ48TM6DPTcW9w3"
},
"logName": "projects/order-management-317713/logs/script.googleapis.com/console_logs",
"receiveTimestamp": "2022-03-10T10:09:59.313440894Z"
}
這是晦澀難懂的,對“未知數”根本沒有幫助。
它參考的函式,供參考:
async function fileMakerPro(e) {
console.time("fileMakerPro");
//Order Management Named Ranges
let OM_NR = await getNamedRangesAsObject_(ss);
let orderNumber, orderFolder, orderFolderName;
let loadingDate, loadingDateFormatted, dueDate, dueDateFormatted;
let sheetGoodsTable = OM_NR.goodsTable.ranges.filter(function (x) { /* here, x is an array, not an object */
return !(x.every(element => element === (undefined || null || '')))
});
//Get order number if exists or show warning and return
if (orderNumber = OM_NR.OrderNo.range.toString()) {
} else {
ui.alert(`?? ORDER NUMBER \(${OM_NR.OrderNo.rangeA1.toString()}\) appears missing, please correct and try again.`);
return;
}
//Get loading date if exists or show warning and return
if (loadingDate = OM_NR.transportLoadingDate.range) {
loadingDateFormatted = `${loadingDate.getDate()}-${loadingDate.getMonth() 1}-${loadingDate.getFullYear()}`;
monthName = monthNames[loadingDate.getMonth()];
//Set Due Date 30 days after Loading Date
dueDate = new Date(loadingDate.getFullYear(), loadingDate.getMonth(), loadingDate.getDate() 30);
dueDateFormatted = `${dueDate.getDate()}-${dueDate.getMonth() 1}-${dueDate.getFullYear()}`;
} else {
ui.alert(`?? LOADING DATE \(${OM_NR.transportLoadingDate.rangeA1.toString()}\) appears to be missing, please correct and try again.`);
return;
}
let rootFolder = DriveApp.getFileById(sheetId).getParents().next();
let tempFolder = DriveApp.getFolderById("1f4Ll-KODzmvBIuunaCS_7anMCX-w86S6");
let monthFolders = rootFolder.getFolders();
let tickBoxes = e.formInputs.generateDocsCheckboxes;
let packingListTemplateId = '1cZUB4U59Z56456gdgdghhka2QQ9sUNIlQSHYy1M';
let tickCMR = false, tickInvoice = false;
//Find existing order folder
let orderSearch = await searchFolders(monthFolders, monthName, orderNumber);
//Set Order Folder Name if both values present
orderFolderName = `${loadingDate.getDate()}-${loadingDate.getMonth() 1}-${loadingDate.getFullYear()} \(${orderNumber}\)`;
if (tickBoxes !== undefined) {
if (tickBoxes.indexOf('tickBoxCMRnote') > -1) {
tickCMR = true;
}
if (tickBoxes.indexOf('tickBoxInvoice') > -1) {
tickInvoice = true;
}
} else {
let confirm = ui.alert(`?? No documents selected. Update Order ${orderNumber} Snapshot and Packing List only?`, Browser.Buttons.YES_NO);
if (confirm === ui.Button.YES) {
fileMakerPro();
} else {
ss.toast(`?? Update cancelled.`);
return;
}
}
if (!orderSearch.foundMonthFolder) {
ss.toast(`?? Creating Month Folder...`);
monthFolder = rootFolder.createFolder(monthName);
} else {
monthFolder = orderSearch.foundMonthFolder;
}
if (!orderSearch.foundOrderFolder) {
ss.toast(`?? Creating Order Folder...`);
orderFolder = monthFolder.createFolder(orderFolderName);
} else {
if (!orderSearch.foundOrderFolder.getName().includes(loadingDateFormatted)) {
ui.alert(`?? Duplicate Order Number ${orderNumber} found: ${orderSearch.foundMonthFolder.getName()} / ${orderSearch.foundOrderFolder.getName()}.\n\n Please change Order Number or remove duplicate Order Folder.`);
return;
}
orderFolder = orderSearch.foundOrderFolder;
}
if (tickInvoice && tickCMR) {
assembleCMR(orderFolder, orderNumber, tempFolder, loadingDateFormatted, sheetGoodsTable, OM_NR);
assembleInvoice(orderFolder, orderNumber, tempFolder, loadingDateFormatted, dueDateFormatted, sheetGoodsTable, OM_NR);
ss.toast(`? Documents Saved`);
} else {
if (tickCMR) {
assembleCMR(orderFolder, orderNumber, tempFolder, loadingDateFormatted, sheetGoodsTable, OM_NR);
ss.toast(`? CMR Document Saved`);
}
if (tickInvoice) {
assembleInvoice(orderFolder, orderNumber, tempFolder, loadingDateFormatted, dueDateFormatted, sheetGoodsTable, OM_NR);
ss.toast(`? Invoice Document Saved`);
}
}
let existingOrderSnapshot = orderFolder.getFilesByName(`${orderNumber} - ORDER SNAPSHOT - DO NOT EDIT`);
let existingPackingList = orderFolder.getFilesByName(`${orderNumber} - PACKING LIST`);
let packingListId = await createPackingList(existingPackingList, orderFolder, orderNumber, packingListTemplateId, sheetId, OM_NR);
createOrderSnapshot(existingOrderSnapshot, orderFolder, orderNumber, sheetId, packingListId);
syncOrderNumbers(orderSearch.orderNumbers);
console.timeEnd("fileMakerPro");
return;
}
I suspect maybe the following function could be causing the Timeout since the loop may be malfunctioning but not sure how to check or fix:
async function writePackingList(OM_NR, packingList, packingListId){
let PL_NR = await getNamedRangesAsObject_(packingList);
for (let nr in PL_NR) {
Logger.log(nr);
if (nr == "loadingAddress") {
packingList.getRangeByName(`${nr}`).setValue(OM_NR[`${nr}`].range);
} else if (nr) {
packingList.getRangeByName(`${nr}`).setValue(OM_NR[`${nr}`].range);
} else {
break;
}
}
ss.getRangeByName("transportTotalNetWeight").setFormula(`=IMPORTRANGE("${packingListId}", "PL!I15")`)
ss.getRangeByName("transportTotalGrossWeight").setFormula(`=IMPORTRANGE("${packingListId}", "PL!H15")`)
}
Any help would be appreciated as I've hit a brick wall with this. I need to figure out how to debug this error, understand why it's happening and fix it so it doesn't happen when fully deployed.
Thanks
EDIT to include additional functions:
//Make copy of Invoice template doc, get body, replace all placeholders, return
async function assembleInvoice(orderFolder, orderNumber, tempFolder, loadingDateFormatted, dueDateFormatted, sheetGoodsTable, OM_NR) {
console.time("assembleInvoice");
ss.toast(`?? Assembling Invoice Document...`);
let prefix = orderNumber " - ";
let fileName = "INVOICE";
let templateTempCopy;
//Blue Invoice Template
let invoiceTemplate1 = DriveApp.getFileById("C2j_q3nUP4UTUR1KiCt07r1lATPKSjzEm-EeY109T8B4");
//Red Invoice Template
let invoiceTemplate2 = DriveApp.getFileById("1uczJT-F-JzKzaBwh_CdhJNcFkgDHfGjypJYom4vqGIo");
//Choose Invoice template based on Movement Type
let staraMovementType = OM_NR.staraMovementType.range;
if (staraMovementType.toString().includes('GB SHIPPING TO')) {
templateTempCopy = invoiceTemplate1.makeCopy(tempFolder);
} else {
templateTempCopy = invoiceTemplate1.makeCopy(tempFolder);
}
//Open working copy
let workingCopy = DocumentApp.openById(templateTempCopy.getId());
//Get body from working copy
let documentBody = workingCopy.getBody();
//Populate table
let allTables = documentBody.getTables();
let invoiceGoodsTable = allTables[3];
let itemRowTemplate = invoiceGoodsTable.getRow(invoiceGoodsTable.getNumRows() - 2);
let totalsRowTemplate = invoiceGoodsTable.getRow(invoiceGoodsTable.getNumRows() - 1);
for (let n in sheetGoodsTable) {
let tableRow = invoiceGoodsTable.appendTableRow(itemRowTemplate.copy());
tableRow.getCell(0).replaceText("{itemNo}", sheetGoodsTable[n][1]);
tableRow.getCell(1).replaceText("{itemDesc}", sheetGoodsTable[n][0]);
tableRow.getCell(2).replaceText("{commodityCode}", sheetGoodsTable[n][2]);
tableRow.getCell(3).replaceText("{cartons}", sheetGoodsTable[n][4]);
tableRow.getCell(4).replaceText("{qtyKgs}", sheetGoodsTable[n][5]);
tableRow.getCell(5).replaceText("{price}", sheetGoodsTable[n][3]);
tableRow.getCell(6).replaceText("{total}", sheetGoodsTable[n][5] * sheetGoodsTable[n][3]);
}
let totalsRow = invoiceGoodsTable.appendTableRow(totalsRowTemplate.copy());
totalsRow.getCell(3).replaceText("{cartons}", OM_NR.transportCasesCartons.range);
totalsRow.getCell(4).replaceText("{qtyKgs}", OM_NR.transportTotalNetWeight.range);
totalsRow.getCell(6).replaceText("{total}", OM_NR.transportInvoiceTotal.range);
itemRowTemplate.removeFromParent();
totalsRowTemplate.removeFromParent();
let importerAddress = `${OM_NR.importerConsigneeIntoEU.range}, ${OM_NR.importerAddress.range}`;
documentBody.replaceText("{currency}", OM_NR.staraInvoiceCurrency.range);
documentBody.replaceText("{shipToAddress}", importerAddress);
documentBody.replaceText("{billToAddress}", importerAddress);
documentBody.replaceText("{exporterCustomsInvoiceNo}", OM_NR.exporterCustomsInvoiceNo.range);
documentBody.replaceText("{exporterVAT}", OM_NR.exporterVAT.range);
documentBody.replaceText("{exporterEORI}", OM_NR.exporterEORI.range);
documentBody.replaceText("{staraOrderNo}", OM_NR.staraOrderNo.range);
documentBody.replaceText("{staraCustomerOrderNo}", OM_NR.staraCustomerOrderNo.range);
documentBody.replaceText("{transportLoadingDate}", loadingDateFormatted);
documentBody.replaceText("{dueDate}", dueDateFormatted);
documentBody.replaceText("{paymentTerms}", "30 DAYS");
documentBody.replaceText("{staraInvoiceNo}", OM_NR.staraInvoiceNo.range);
documentBody.replaceText("{incoTerms}", `${OM_NR.orderIncoterm.range} ${OM_NR.orderCountryOfDestination.range}`);
documentBody.replaceText("{transportTotalGrossWeight}", OM_NR.transportTotalGrossWeight.range);
documentBody.replaceText("{transportTotalNetWeight}", OM_NR.transportTotalNetWeight.range);
documentBody.replaceText("{transportTruckRef}", OM_NR.transportTruckRef.range);
documentBody.replaceText("{transportSeal1}", OM_NR.transportSeal1.range);
documentBody.replaceText("{transportSeal2}", OM_NR.transportSeal2.range);
documentBody.replaceText("{transportInvoiceTotal}", OM_NR.transportInvoiceTotal.range);
documentBody.replaceText("{staraInvoiceCurrency}", OM_NR.staraInvoiceCurrency.range);
workingCopy.saveAndClose();
//Gets a 'blob' of the completed document
let completedDoc = templateTempCopy.getAs('application/pdf');
//Check for existing PDF and move to trash (not fully delete)
let foundFile = orderFolder.getFilesByName(prefix fileName);
if (foundFile.hasNext()) {
foundFile.next().setTrashed(true);
}
try {
//Create PDF
ss.toast(`?? Saving ${fileName} PDF...`);
orderFolder.createFile(completedDoc).setName(prefix fileName);
deleteTempFiles(templateTempCopy.getId());
} catch (err) {
showError(err);
} finally {
ss.toast(`? Invoice Document Saved`);
console.timeEnd("assembleInvoice");
}
return;
}
async function createPackingList(existingPackingList, orderFolder, orderNumber, packingListTemplateId, sheetId, OM_NR) {
console.time("createPackingList");
let packingListId;
//Get current sheet container objects and data
if (existingPackingList.hasNext()) {
packingListId = existingPackingList.next().getId();
} else {
ss.toast(`?? Creating Packing List...`);
let newPackingList = DriveApp.getFileById(packingListTemplateId);
let newPackingListCopy = newPackingList.makeCopy(`${orderNumber} - PACKING LIST`, orderFolder)
packingListId = newPackingListCopy.getId();
}
let packingList = SpreadsheetApp.openById(packingListId);
addImportrangePermission(packingListId, sheetId);
writePackingList(OM_NR, packingList, packingListId);
ss.toast(`? Packing List Created/Updated`);
console.timeEnd("createPackingList");
return packingListId;
}
async function createOrderSnapshot(existingOrderSnapshot, orderFolder, orderNumber, sheetId, packingListId) {
console.time("createOrderSnapshot");
let snapshotExists = existingOrderSnapshot.hasNext();
//If snapshot exists, delete.
if (snapshotExists) {
existingOrderSnapshot.next().setTrashed(true);
ss.toast(`?? Updating Order Snapshot...`);
} else {
ss.toast(`?? Creating Order Snapshot...`);
}
//Make copy of sheet in order folder
let currentSheet = DriveApp.getFileById(sheetId);
let sheetCopy = currentSheet.makeCopy(`${orderNumber} - ORDER SNAPSHOT - DO NOT EDIT`, orderFolder);
let sheetCopyId = sheetCopy.getId();
let targetSpreadsheet = SpreadsheetApp.openById(sheetCopyId);
//let targetSpreadsheet = SpreadsheetApp.openById(DriveApp.getFileById(sheetId).makeCopy(`${orderNumber} - ORDER SNAPSHOT - DO NOT EDIT`, orderFolder).getId());
addImportrangePermission(targetSpreadsheet.getRangeByName("CONTROL").getValue(), sheetCopyId);
addImportrangePermission(packingListId, sheetCopyId);
targetSpreadsheet.getRangeByName("transportTotalNetWeight").setFormula(`=IMPORTRANGE("${packingListId}", "PL!I15")`)
targetSpreadsheet.getRangeByName("transportTotalGrossWeight").setFormula(`=IMPORTRANGE("${packingListId}", "PL!H15")`)
targetSpreadsheet.getRangeByName("topRow").clearDataValidations()
targetSpreadsheet.getRangeByName("sheetBody").clearDataValidations()
//DELETE UNNEEDED TABS FROM COPY
targetSpreadsheet.deleteSheet(targetSpreadsheet.getSheetByName("PC"));
targetSpreadsheet.deleteSheet(targetSpreadsheet.getSheetByName("C1"));
targetSpreadsheet.deleteSheet(targetSpreadsheet.getSheetByName("C2"));
targetSpreadsheet.deleteSheet(targetSpreadsheet.getSheetByName("SFC"));
if (snapshotExists) {
ss.toast(`? Order Snapshot Updated`);
} else {
ss.toast(`? Order Snapshot Created`);
}
console.timeEnd("createOrderSnapshot");
return;
}
async function addImportrangePermission(sourceSheetId, authSheetId) {
console.time("addImportrangePermission");
if (sourceSheetId) {
// donor or source spreadsheet id
// adding permission by fetching this url
let url = `https://docs.google.com/spreadsheets/d/${authSheetId}/externaldata/addimportrangepermissions?donorDocId=${sourceSheetId}`;
let token = ScriptApp.getOAuthToken();
let params = {
method: 'post',
headers: {
Authorization: 'Bearer ' token,
},
muteHttpExceptions: true
};
UrlFetchApp.fetch(url, params);
}
console.timeEnd("addImportrangePermission");
return;
}
uj5u.com熱心網友回復:
問題:
在 Workspace 插件中,Action觸發時執行的回呼函式被限制為30 秒的執行時間:
Apps 腳本卡服務將回呼函式限制為最長 30 秒的執行時間。如果執行時間超過此時間,您的附加 UI 可能無法正確更新其卡片顯示以回應Action。
筆記:
由于您沒有提供與花費最多時間的功能相關的代碼(例如assembleCMR, assembleInvoice, createPackingList),因此我無法對此提出任何建議,但無論如何您應該嘗試提高這些功能的效率,或者將其全部拆分為幾個Actions。
參考:
- 回呼函式
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/442358.html
標籤:google-apps-script google-workspace-add-ons
