synchronous Lambda Retry (2) (feat. S3 trigger Lambda)

Falcon·2021년 8월 19일
1

aws

목록 보기
16/35

🎯 Goal

  • S3에 이벤트 발생(생성, 삭제 등)으로 람다를 트리거시킬 수 있다.
  • 트리거된 람다에서 S3 파일을 핸들링 할 수 있다.
  • 👉 최종적으로, 이미 전에 실패했던 에러 로그에 만 파싱하여 에러핸들링을 할 수 있다.

Mistake

CloudWatch Logs의 모든 로그 이벤트는 이미 gzip 형식으로 압축되어 있으므로 Firehose의 압축 구성을 비압축으로 유지해야 이중으로 압축되는 것을 방지할 수 있습니다.

- AWS Document

Lambda Function Source Code


import {S3} from 'aws-sdk';
import {S3Event} from 'aws-lambda';
import {Buffer} from 'buffer';


const s3Client = new S3({ apiVersion: 'latest', region: process.env.AWS_REGION });


export async function bucketHandler (event: S3Event) {
  console.dir(event.Records);
  // Get the object from the event and show its content type

  const bucket = event.Records[0].s3.bucket.name;
  const key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' '));
  const params : GetObjectCommandInput = {
    // Bucket: the bucket name containing the object
    Bucket: bucket,
    // Key: Key of the object to get (file name)
    Key: key,
    ResponseContentEncoding: 'gzip',
    ResponseContentType: 'text/plain; charset=utf-8'
  };

  try {
    // Body — (Buffer(Node.js), Typed Array(Browser), ReadableStream) // 2006 version, aws-sdk
    const { Body } = await s3Client.getObject(params).promise();

    const resultString = Body.toString('utf-8');
    // 이 부분이 잘못되었다.
    console.log(resultString);

    return resultString;
  } catch (error) {
    console.log(error);
    const message = `Error getting object from bucket ${bucket}. Make sure they exist and your bucket is in the same region as this function.`;
    console.log(message);
    throw new Error(message);
  }
};

다음 부분에 잘못된게 있다.

    const { Body } = await s3Client.getObject(params).promise();
    const resultString = Body.toString('utf-8');
    // 이 부분이 잘못되었다.
    console.log(resultString);

S3 에 올라가있는 파일 오브젝트의 Body만 읽어오면 된다고 생각했는데

막상 로그를 찍어보니 왠 Uint8Array Buffer 가 출력된다.
바로 toString('utf-8') 해보니 인코딩된게 깨져보이는 것을 확인할 수 있었다.

🤔 왜 받아온 Object가 Uint8Array 인가? + 왜 깨져보이는가?

별도의 압축형식을 지정하지 않아도 모든 파일은 .gz 형식으로 압축되어있다.
즉, .gz 파일을 Uint8Array || toString 한 값이 '압축된 파일 스트림' 그 자체인것이다.

🔑 그럼 어떻게하지?

.gz 파일은 압축된 파일이므로 압축을 풀어주기만 하면된다.

import * as zlib from 'zlib';
// Body 는 .gz 파일의 스트림 (TypedArray) 이므로 압축을 해제해주자.
    const bufferedString = zlib.gunzipSync(Body as Uint8Array);
// ...
// processing..

정상 출력 결과

🙂 S3 Object 파일 파싱성공!


🔗 Reference

profile
I'm still hungry

0개의 댓글