Hey there! I'm currently working on a TypeScript async function in an AWS Lambda environment to process data stored in S3 using `s3.selectObjectContent`. The goal is to extract certain values and then write them into a DynamoDB table using `dynamoDb.putItem`. However, I encountered an error where the S3 payload data variable is reported as undefined before the s3 command completes. Despite this error, the function still manages to write to the database table asynchronously. Could you provide any insights on how I can improve this code or suggest potential fixes?
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) && (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
}
}
Error Message at Runtime (even though it completes the job!
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)"]}