上传到 S3 Bucket 时如何解决最大执行时间问题?

How to work around maximum execution time when uploading to S3 Bucket?

我正在使用 S3-for-Google-Apps-Script library to export full attachments from Gmail to an S3 bucket. I changed the S3 code to upload the actual content of the attachment rather than an encoded string, as detailed in

但是,当尝试上传大约 > 5 MB 的附件时,应用程序脚本会抛出以下错误:“已超过最大执行时间”。我使用时间戳来衡量时间的差异,以确保时间问题发生在s3.putObject(bucket,objectKey,file)函数中。

注意对于刚刚超过限制的文件,它仍会上传到我的 s3 存储桶,但应用程序脚本 returns 执行时间已超过(30 秒)到用户,扰乱用户流。


可重现的例子

这基本上是一个简单的按钮,可以为所有附件抓取当前电子邮件,如果它们是 pdf 文件,则它会调用导出功能。并将这些附件导出到我们的 s3 实例。问题是当文件 > 5mb 时,它会抛出错误:

"exportHandler exceeded execution time"

如果您要重现此内容,请注意您需要复制 s3 for gas and initialize that as a separate library in apps script with the changes made .

的一个实例

为了 link 库,转到文件>库,并在 google 应用程序脚本控制台中添加相应的库 ID、版本和开发模式。您还需要将 AWS 访问密钥和秘密密钥保存在 属性 服务缓存中,如库文档中所述。

  1. 在当前 Gmail 线程上触发单个附件导出的初始按钮:
export default function testButton() {
  const Card = CardService.newCardBuilder();
  const exportButtonSection = CardService.newCardSection();
  const exportWidget = CardService.newTextButton()
    .setText('Export File')
    .setOnClickAction(CardService.newAction().setFunctionName('exportHandler'));
  exportButtonSection.addWidget(exportWidget);
  Card.addSection(exportButtonSection);
  return Card.build();
}
  1. 将附件导出到指定的 s3 存储桶。请注意,S3Modified 是根据上面概述的 post 修改的 google 应用程序脚本的 s3 实例,它是一个单独的 Apps 脚本文件,s3.putObject 需要很长时间是时候处理附件了(我认为这是错误发生的地方)。

  2. 凭据初始化您的 s3 awsAccessKeyawsBucket,并且可以存储在 PropertiesService.

function exportAttachment(attachment) {
  const fileName = attachment.getName();
  const timestamp = Date.now();
  const credentials = PropertiesService.getScriptProperties().getProperties();
  const s3 = S3Modified.getInstance(credentials.awsAccessKeyId, credentials.awsSecretAccessKey);
  s3.putObject(credentials.awsBucket, fileName, attachment, { logRequests: true });
  const timestamp2 = Date.now();
  Logger.log('difference: ', timestamp2 - timestamp);
}
  1. 这会获取当前电子邮件中的所有 PDF 附件,此功能与应用程序脚本站点上用于处理 Gmail 附件的功能几乎相同,但它专门查找 pdf(不是要求代码):
function getAttachments(event) {
  const gmailAccessToken = event.gmail.accessToken;
  const messageIdVal = event.gmail.messageId;

  GmailApp.setCurrentMessageAccessToken(gmailAccessToken);
  const mailMessage = GmailApp.getMessageById(messageIdVal);

  const thread = mailMessage.getThread();
  const messages = thread.getMessages();
  const filteredAttachments = [];
  for (let i = 0; i < messages.length; i += 1) {
    const allAttachments = messages[i].getAttachments();
    for (let j = 0; j < allAttachments.length; j += 1) {
      if (allAttachments[j].getContentType() === 'application/pdf') {
        filteredAttachments.push(allAttachments[j]);
      }
    }
  }
  return filteredAttachments;
}

  1. 单击按钮时获取附件并将​​其导出到 s3 存储桶的全局处理程序:
function exportHandler(event) {
  const currAttachment = getAttachments(event).flat()[0];
  exportAttachment(currAttachment);
}
global.export = exportHandler;

绝对清楚,大部分时间是在第二个代码示例 (exportAttachment) 中处理的,因为这是将对象放入 s3 应用程序的地方。

时间戳有助于记录该函数花费的时间,使用 300kb 的文件对其进行测试,您将得到 2 秒,4mb 20 秒,>5mb 大约 30 秒。这部分对最大执行时间的贡献最大。


这就是我提出问题的原因,为什么我会收到超出最大执行时间的错误,我该如何解决?以下是我对潜在解决方案的两个想法:

  1. 为什么会出现执行限制? quotas 表示自定义函数的运行时间限制为 30 秒,脚本的运行时间限制为 6 分钟。

    经过一些研究,我只在 Google 表格中的 AddOns 上下文中发现了自定义函数提及,但我得到错误的函数是我的全局函数(以便它可以被回调识别)脚本。有没有办法将其更改为不被识别为自定义函数,以便我不受 30 秒执行限制?

  2. 现在,我该如何解决这个执行限制?这是建议修改 中的 S3 库的问题吗?本质上,修改建议我们导出附件的实际字节而不是编码字符串。

    这肯定会增加 Apps 脚本必须处理的负载,这就是它增加所需执行时间的原因。我该如何解决这个问题?有没有办法改变S3库来提高处理速度?

关于第一个问题

来自https://developers.google.com/gsuite/add-ons/concepts/actions#callback_functions

Warning: The Apps Script Card service limits callback functions to a maximum of 30 seconds of execution time. If the execution takes longer than that, your add-on UI may not update its card display properly in response to the Action.

关于第二个问题

answer to Google Apps Script Async function execution on Server side 上,建议 "hack":使用 "open link" 操作来调用可以 运行 异步执行需要很长时间的任务的操作 运行.

相关

  • How to use HtmlService in Gmail add-on using App Script
  • Handling Gmail Addon Timeouts

rev 1 的答案。

关于第一个问题

在 Google Apps 脚本中,自定义函数 是要在 Google 表格公式中使用的函数。没有办法不扩展这个限制。参考https://developers.google.com/app-script/guides/sheets/functions

onOpenonEdit 简单触发器也有 30 秒的执行时间限制。参考文献https://developers.google.com/apps-script/guides/triggers

正在从 Google Apps 脚本编辑器执行的功能、自定义菜单、已分配功能的图像、可安装触发器、客户端代码、Google Apps 脚本 API常规 Google 帐户(例如那些具有 @gmail.com 电子邮件地址的帐户)的执行时间限制为 6 分钟,而 G Suite 帐户的执行时间限制为 30 分钟。