Ошибка времени выполнения «Ошибка типа: не удается прочитать свойство «Полезная нагрузка» неопределенного» -> во время aws s3 selectObjectContent и dynamodb PutItem

#typescript #asynchronous #amazon-s3 #aws-lambda #amazon-dynamodb

#typescript #асинхронный #amazon-s3 #aws-lambda #amazon-dynamodb

Вопрос:

Привет, я пишу асинхронную функцию на основе typescript (aws lambda function) для обработки данных в aws s3 с помощью s3.selectObjectContent и записываю извлеченное значение в таблицу в dynamodb при использовании dyanmodb.PutItem. Я получаю сообщение об ошибке, когда обрабатываются данные s3, но функция (при асинхронном вызове) все еще завершает запись в таблицу базы данных. По какой-то причине переменная, в которой хранятся данные полезной нагрузки s3, сообщается как неопределенная до завершения команды s3 и возврата обещания. Можете ли вы помочь мне найти лучший способ написания этого кода или предложить, как я могу это исправить?

 export class Handler {
    import { S3, DynamoDB } from 'aws-sdk'
    import { DID_TABLENAME, IP_DEVICE_HISTORY_TABLENAME } from './Constants'
      dynamodb = new DynamoDB()
      s3 = new S3()

      async handle(event: SQSEvent): Promise<void> {
       console.log('Entering handler')
       console.log(event)
       this.srcBucket = 'my-bucket'
       this.srcKey = 'myfile.gzip'
       await this.prepareAndQuery()
     }
      private async prepareAndQuery(): Promise<any> {
             console.log('Preparing params')
             const params = {
             Bucket: this.srcBucket,
             Key: this.srcKey,
             ExpressionType: 'SQL',
             Expression: 'SELECT * FROM s3object',
             InputSerialization: { CompressionType: 'GZIP', JSON: { Type: 'LINES' }},
             OutputSerialization: { JSON: { RecordDelimiter: ' ' }}}
             console.log('Sending s3 command')
             try {
               this.s3selectOutput = await this.s3.selectObjectContent(params).promise()
               const events: any = this.s3selectOutput.Payload
               for await (const event of events) {
                 try {
                       if(event.Records) {
                       // THIS LINE BELOW IS THE POINT OF FAILURE 
                       const s3selectOutput: any = event.Records.Payload.toString()
                       const decoded = decodeURIComponent(s3selectOutput.replace(/ |t/g, ' '))
                       const jsoncontent = JSON.parse(decoded)
                       const udid = jsoncontent.pyAppResponse.logs.udid_logs.udid;
                       const did = jsoncontent.pyAppResponse.logs.udid_logs.did;
                       if ((did !== null) amp;amp; (udid !== null)) {
                          events.pause()
                          const paramsdiddB = {
                          Item: {
                          'did': { S: did },
                          'udid': { S: udid }},
                          ReturnConsumedCapacity: 'TOTAL',
                          TableName: DID_TABLENAME }
                          console.log(`going to write to dbs ${DID_TABLENAME}`)
                          const _retValue = await this.dynamodb.putItem(paramsdiddB).promise().then((_dBdata: any) => {
                            console.log(`Successfuly wrote to tables: ${DID_TABLENAME}`)
                              }).catch((dBerr: any) => {
                                console.log('Error writing to database tables')
                                console.log(dBerr.stack)
                              })
                              events.resume()
                            }
                          }
                        }
                        catch (s3undefinederr) {
                          if (s3undefinederr instanceof TypeError) {
                            console.log(s3undefinederr)
                            throw s3undefinederr
                          }
                        }
                        if (event.End !== null) {
                          console.log('SelectObjectContent completed')
                        }
                      }
                    }
                    catch (s3error) {
                      console.log(s3error)
                      throw s3error
                    }
                    return this.s3selectOutput
                  }
   }
  

Сообщение об ошибке во время выполнения (даже если оно завершает работу!

     at Handler.<anonymous> (/var/task/build/dist/Handler.js:144:66)
    at Generator.next (<anonymous>)
    at fulfilled (/var/task/build/dist/Handler.js:5:58)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
2020-09-30T04:58:57.312Z    9783b6c9-d88e-4b14-82d0-607bd14ec730    ERROR   Invoke Error    {"errorType":"TypeError","errorMessage":"Cannot read property 'Payload' of undefined","stack":["TypeError: Cannot read property 'Payload' of undefined","    at Handler.<anonymous> (/var/task/build/dist/Handler.js:144:66)","    at Generator.next (<anonymous>)","    at fulfilled (/var/task/build/dist/Handler.js:5:58)","    at processTicksAndRejections (internal/process/task_queues.js:97:5)"]}```
  

Ответ №1:

Я смог исправить эту ошибку, обнаружив ошибку с помощью инструкции try catch, которая выглядит следующим образом

 catch (s3undefinederr) {
 console.log(s3undefinederr)
 if (s3undefinederr instanceof Error) {
   throw s3undefinederr
 }
}