【问题标题】:S3.getObject() works locally but not on LambdaS3.getObject() 在本地工作,但不适用于 Lambda
【发布时间】:2019-09-11 04:59:40
【问题描述】:

我有一个由 S3 上传触发的 Lambda 函数。我想使用 readStreamer 读取上传文件的内容。

const shouldUseXray = false

export async function handleSplitSpreadsheet (event, context) {
  context.callbackWaitsForEmptyEventLoop = false
  if (shouldUseXray) {
    const { captureAsyncFunc } = require('../../../lib/xray_promise')
    await captureAsyncFunc('handleSplitSpreadsheet', () => {
      log('event', { event })
      processLargeSpreadsheet(event, context)
    })
  } else {
    processLargeSpreadsheet(event, context)
  }
}

export async function processLargeSpreadsheet (event, context) {
  await Promise.all(event.Records.map(async (s3Record) => {
    const bucketName = s3Record.s3.bucket.name
    const s3ObjectMeta = s3Record.s3.object
    const s3ObjectKey = s3ObjectMeta.key
    const s3ObjectSize = s3ObjectMeta.size
    try {
      const s3ObjectStream = s3.getObject({
        Bucket: bucketName,
        Key: s3ObjectKey,
      }).createReadStream()
      s3ObjectStream.setEncoding('utf8')
      s3ObjectStream.on('open', function (data) {
        log('Open:', data)
      })
      s3ObjectStream.on('error', function (data) {
        log('Error: ', data)
      })
      s3ObjectStream.on('data', function (data) {
        log('Data: ', data)
      })
      s3ObjectStream.on('end', function (data) {
        log('End: ', data)
      })
    } catch (err) {
      log('Error: ', err)
    }
  }))
}

如果我使用 sls invoke --path event.json 在本地调用此函数,作为 s3 产生的确切事件的 event.json,该文件将打印在控制台上。 如果我将文件上传到 S3,则不会打印任何内容。即使我将它全部包装在 try/catch 中,也不会捕获任何错误。

serverless.yml 允许 getObject 用于 s3。

iamRoleStatements:
- Effect: "Allow"
  Action:
    - "s3:GetObject"
    - "s3:PutObject"
    - "s3:DeleteObject"
  Resource: "arn:aws:s3:::my-s3-bucketr-foo"

【问题讨论】:

  • 能贴出整个 lambda 函数吗?

标签: amazon-s3 aws-lambda serverless-framework


【解决方案1】:

processLargeSpreadsheet 函数在调用流回调之前返回,这会导致 lambda 函数终止,因此在 lambda 中运行时看不到这些日志。在本地运行时,即使processLargeSpreadsheet 返回,回调仍然会执行。要解决这个问题,您可以将流回调包装在一个 Promise 中,然后像这样等待:

export async function processLargeSpreadsheet (event, context) {
  await Promise.all(event.Records.map(async (s3Record) => {
    const bucketName = s3Record.s3.bucket.name
    const s3ObjectMeta = s3Record.s3.object
    const s3ObjectKey = s3ObjectMeta.key
    const s3ObjectSize = s3ObjectMeta.size

    await new Promise((resolve, reject) => {
      try {
        const s3ObjectStream = s3.getObject({
          Bucket: bucketName,
          Key: s3ObjectKey,
        }).createReadStream()
        s3ObjectStream.setEncoding('utf8')
        s3ObjectStream.on('open', function (data) {
          log('Open:', data)
        })
        s3ObjectStream.on('error', function (data) {
          log('Error: ', data)
          reject();
        })
        s3ObjectStream.on('data', function (data) {
          log('Data: ', data)
        })
        s3ObjectStream.on('end', function (data) {
          log('End: ', data)
          resolve();
        })
      } catch (err) {
        log('Error: ', err)
        reject();
      }
    })
  }))
}

您可能还需要在handleSplitSpreadsheet 中等待processLargeSpreadSheet

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-03
    • 1970-01-01
    • 1970-01-01
    • 2021-05-27
    相关资源
    最近更新 更多