Лямбда случайно пропускает файлы, создает дубликаты в S3

#node.js #aws-lambda

#node.js #aws-lambda

Вопрос:

У меня есть функция lambda для приема изображений из корзины S3, получения некоторых метаданных, сохранения их в экземпляре AWS RDS, а затем повторной загрузки изображения. Должно быть просто, но я боюсь, что одно из следующих вызывает проблемы.

  • Иногда создает дубликаты
  • Иногда пропускает файлы

Похоже, это происходит с большими наборами изображений. Я загрузил ресурсы до 1000, и, похоже, он работает достаточно хорошо. 3000 кажется ненадежным. Функция не установлена на тайм-аут слишком рано (30 секунд должно быть в порядке), у нее хорошее выделение памяти 512 МБ (пожалуйста, скажите мне, если это ложные предположения. Я любитель в этом и новичок в Lambda, поэтому, пожалуйста, дайте мне знать, что, по вашему мнению, я сделал.

 const AWS = require('aws-sdk')
const uuidv4 = require('uuid/v4');
AWS.config.update({
    accessKeyId: 'XXX',
    secretAccessKey: 'XXX'
})
const s3 = new AWS.S3({
    signatureVersion: 'v4',
    region: 'eu-west-2'
})
const hasha = require('hasha')
const { Pool, Client } = require('pg')
const pool = new Pool({
  user: 'XXX',
  host: 'XXX',
  database: 'XXX',
  password: 'XXX',
  port: 5432,
})


exports.handler = async (event, context) => {
    const bucket = event.Records[0].s3.bucket.name;
    const key = decodeURIComponent(event.Records[0].s3.object.key.replace(/ /g, ' '));
    console.log("Processing: "   key)
    //Get file
    try {
        const file = await s3.getObject({
            Bucket: bucket,
            Key: key
        }).promise()
        const hash = await hasha(file.Body, { algorithm: 'md5' })
        const id = uuidv4()
        newfile = await s3.putObject({
            Bucket: 'XXX',
            Key: id,
            Body: file.Body,
            ContentType: file.ContentType
        }).promise()
        var fileString = key.split('/')
        var fileName = fileString[fileString.length - 1]
        const text = 'INSERT INTO original(original_filename, mime, file_size, file_path, file_name, hash) VALUES($1, $2, $3, $4, $5, $6) RETURNING *'
        const values = [fileName, file.ContentType, file.ContentLength, key, id, hash]
        const res = await pool.query(text, values)
        console.log(res.rows[0])
        return "Done"
    } catch (err) {
        console.log("####### Error #######: ", err)
        return "Error"
    }

}

  

Я ожидаю, что будет загружено X файлов, и столько же будет в целевой корзине и в моей таблице БД. Это не всегда так, и сложно определить, где что-то идет не так. Я уверен, что есть более элегантный способ сделать это.

Комментарии:

1. Несколько вещей, которые я бы сделал с места в карьер — переместите try { , чтобы закрыть начало и добавить уникальное ограничение к таблице, в которую вы вставляете. Тогда вы будете получать ошибки при возникновении условий, которых вы хотите избежать, что упрощает отладку.

2. Уникальные ограничения — хорошая идея. Не могли бы вы подробнее остановиться на идее расширения инструкции try? Я попробую, но мне очень хочется знать, какова логика.

3. Какие-либо ошибки в ваших журналах CloudWatch? Также проверьте ошибки и показатели продолжительности вашей лямбды, чтобы узнать, есть ли какие-либо тайм-ауты. Одна вещь, которая может объяснить дубликаты, — это тот факт, что в случае ошибки ваша лямбда повторит попытку (см. docs.aws.amazon.com/lambda/latest/dg/retries-on-errors.html ) и ваш лямбда-код может выйти из строя между putObject и pool.query , что приведет к дублированию объектов в вашей целевой корзине.

4. @JamieDunbar Я не вижу ничего плохого в этом раннем коде, но мне нравится быть уверенным, что он учтен, когда неизвестные ошибки могут повлиять на мой код.