簡體   English   中英

嘗試從 Nodejs 中的 AWS Lambda 函數讀取 S3 存儲桶的內容時未獲得結果

[英]Not getting results when attempting to read the content of an S3 bucket from AWS Lambda function in Nodejs

在將 dynamodb 表從不同賬戶跨賬戶遷移到我們自己的 AWS 賬戶后,我需要使用 nodejs lambda 來讀取和處理包含 json 的文本文件。 通過創建 EMR 集群運行導入作業的源 AWS Datapipeline 在源賬戶(不是我們的賬戶)的 S3 存儲桶中刪除了 5 MB 文件,對象鍵的格式為dynamodbtablename/manifestdynamodbtablename/2c561e6c-62ba-4eab-bf21-7f685c7c3129 清單文件包含以下示例數據:

{"name":"DynamoDB-export","version":3,
"entries": [
{"url":"s3://bucket/dynamodbtablename/2c561e6c-62ba-4eab-bf21-7f685c7c3129","mandatory":true}
]}

我今天大部分時間都在努力閱讀清單文件。 雖然在 lambda 中沒有遇到訪問問題,但我最初必須處理在 terraform 中設置資源的跨賬戶策略和權限。 我現在的問題是調用s3.getObject的代碼似乎沒有被命中。

/* eslint-disable no-console, no-param-reassign */

const AWS = require('aws-sdk');

const massiveTables = [
  'dynamodbtablename'
];

function getS3Objects(params) {
  let s3 = new AWS.S3({
    apiVersion: '2012-10-29'
  });
  return new Promise((resolve, reject) => {
    s3.getObject(params, (err, data) => {
      if (err) {
        reject(err);
      } else {
        resolve(data);
      }
    });
  });
}

const handler = async ({ Records }) => {
  const completelyProcessedSNSPromises = Records.map(async ({ Sns: { Message: tableName } }) => {
    console.log(`tableName: ${tableName}`);
    let massiveTableItem = tableName.trim();
    console.log(`massiveTableItem: ${massiveTableItem}`);
    //#1: Validate the the right table names are coming through
    if (massiveTables.includes(massiveTableItem)) {
      //#2: Use the table name to fetch the right keys from the S3 bucket

      let params = {
        Bucket: process.env.DATA_BUCKET,
        Key: `${massiveTableItem}/manifest`,
        ResponseContentType: 'application/json'
      };

      getS3Objects(params)
        .then(result => {
          console.log(`result: ${result}`);
        })
        .catch(error => {
          console.log(`error: ${error}`);
        });
    }
  });

  await Promise.all(completelyProcessedSNSPromises)
    .then(console.log)
    .catch(console.error);
};

module.exports.handler = handler;

這就是我在 Cloudwatch 日志中得到的信息


16:13:25
2020-03-11T16:13:25.271Z    8bd74c44-c9b1-4cd9-a360-251ad4253eae    INFO    tableName: dynamodbtablename
2020-03-11T16:13:25.271Z    8bd74c44-c9b1-4cd9-a360-251ad4253eae    INFO    tableName: dynamodbtablename

16:13:25
2020-03-11T16:13:25.271Z    8bd74c44-c9b1-4cd9-a360-251ad4253eae    INFO    massiveTableItem: dynamodbtablename
2020-03-11T16:13:25.271Z    8bd74c44-c9b1-4cd9-a360-251ad4253eae    INFO    massiveTableItem: dynamodbtablename

16:13:25
2020-03-11T16:13:25.338Z    8bd74c44-c9b1-4cd9-a360-251ad4253eae    INFO    [ undefined ]
2020-03-11T16:13:25.338Z    8bd74c44-c9b1-4cd9-a360-251ad4253eae    INFO    [ undefined ]

請幫助我知道我做錯了什么。

非常感謝您提前。 PS:我是 Nodejs/Javascript 的新手

您需要在處理程序函數中返回getS3Objects調用。 您沒有返回,因此 map 不會返回 promise,因此不會調用它。

此外,aws-sdk 支持承諾,因此您無需將它們包裝在承諾中。 像這樣的東西

/* eslint-disable no-console, no-param-reassign */

const AWS = require("aws-sdk");

const massiveTables = [
  "dynamodbtablename"
];

function getS3Objects(params) {
  const s3 = new AWS.S3({
    "apiVersion": "2012-10-29"
  });
  return s3.getObject(params).promise();
}

// eslint-disable-next-line func-style
const handler = async ({Records}) => {
  const completelyProcessedSNSPromises = Records.map(async ({"Sns": {"Message": tableName}}) => {
    console.log(`tableName: ${tableName}`);
    const massiveTableItem = tableName.trim();
    console.log(`massiveTableItem: ${massiveTableItem}`);
    // #1: Validate the the right table names are coming through
    if (massiveTables.includes(massiveTableItem)) {
      // #2: Use the table name to fetch the right keys from the S3 bucket

      const params = {
        "Bucket": process.env.DATA_BUCKET,
        "Key": `${massiveTableItem}/manifest`,
        "ResponseContentType": "application/json"
      };

      return getS3Objects(params);
    }
  });

  await Promise.all(completelyProcessedSNSPromises)
    .then(console.log)
    .catch(console.error);
};

module.exports.handler = handler;

謝謝大家的幫助。

我發現問題是我在異步 lambda 處理程序中調用的異步函數由於無法訪問封閉的異步 lambda 處理程序范圍的范圍問題而無法執行。 這發生在使用數組映射和 forEach 函數時。

我求助於使用傳統的 for 循環。

for (let i = 0; i < Records.length; i++) {
    const tableName = Records[i].Sns.Message;
    console.log(`DAZN tableName: ${tableName}`);
    const tableIndex = daznTables.findIndex(t => tableName.includes(t));
    const massiveTableItem = massiveTables[tableIndex];
    console.log(`massiveTableItem: ${massiveTableItem}`);
    const dataBucket = process.env.DATA_BUCKET;
}

由於實際上並不需要從 .map 函數返回任何內容,因此我擺脫了

  await Promise.all(completelyProcessedSNSPromises)
    .then(console.log)
    .catch(console.error);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM