Не получаются результаты при попытке прочитать содержимое корзины S3 из AWS лямбда-функции в Nodejs - PullRequest
0 голосов
/ 12 марта 2020

После перекрестной миграции таблиц динамодаба из другой учетной записи в нашу собственную учетную запись AWS у меня есть требование использовать nodejs лямбду для чтения и обработки текстовых файлов, содержащих json. Источник AWS Datapipeline, который запустил задание импорта путем создания кластера EMR, отбросил 5 МБ файлов в корзину S3 в исходной учетной записи (не в нашей учетной записи) с ключами объектов в формате dynamodbtablename/manifest и dynamodbtablename/2c561e6c-62ba-4eab-bf21-7f685c7c3129. Файл манифеста содержит следующие примеры данных:

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

Я боролся за чтение файла манифеста большую часть дня. Хотя проблем с доступом в лямбде не возникало, изначально мне приходилось сталкиваться с настройкой политик и разрешений между учетными записями для ресурсов в 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

Ответы [ 2 ]

0 голосов
/ 19 марта 2020

Спасибо всем за помощь.

Я обнаружил, что проблема заключается в том, что асин c функция, которую я вызывал в асин c лямбда-обработчике, не смогла выполнить из-за проблем с областью действия относительно их неспособности получить доступ к объему lynda-обработчика asyn c. Это произошло во время использования карты Array и функций forEach.

Я прибег к использованию традиционного для l oop.

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;
}

Поскольку на самом деле не нужно ничего возвращать из. функция карты, я избавился от

  await Promise.all(completelyProcessedSNSPromises)
    .then(console.log)
    .catch(console.error);
0 голосов
/ 12 марта 2020

Вам необходимо вернуть вызов getS3Objects в вашей функции обработчика. Вы не возвращаетесь, поэтому карта не возвращает обещания и, следовательно, она не вызывается.

Кроме того, 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;

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...