misantronic
misantronic

Reputation: 1211

lambda@edge timeout and s3 image processing

I use a lambda@edge function to resize images on the fly. this works quite well - except when calling this function f.e. 5x at the same time. then the lookup for the image on s3 takes ~4 seconds. since lambda@edge functions only have a max. timeout of 5s, I have only 1s left which is way too little to process an image.

So I was asking myself, why is the limit sooo low at 5s?

Maybe I can optimize the s3-lookup for the image which takes 4s when calling the function multiple times (when only calling it for 1 image, its really fast at 200ms).

s3 lookup:

export async function s3ObjectExists(Key: string, Bucket = BucketFiles) {
    try {
        await s3HeadObject(Key, Bucket);
    } catch (e) {
        if (e && e.code === 'NotFound') {
            return false;
        }

        throw new Error(e);
    }

    return true;
}

whole code of the lambda@edge function (simplified):

exports.handler = async (e) => {
    const { request, response } = e.Records[0].cf;
    const q = getQuery(request.querystring);
    const { uri } = request;

    const match = uri.match(/^\/((.+)\.(png|jpg|jpeg))/i);
    const key = match[1];
    const keyWithoutExt = match[2];
    const keyExt = match[3] as 'jpg' | 'png';
    const ext = q.format === 'webp' ? 'webp' : keyExt.toLowerCase();
    const newKey = getKey(`${keyWithoutExt}${JSON.stringify(q)}.${keyExt}`);

    if (await s3ObjectExists(newKey, bucketTmp)) {
        const file = await s3GetObject(newKey, bucketTmp);

        response.body = file.Body.toString('base64');
    } else {
        const file = await s3GetObject(key, bucket);

        let sharpConfig = sharp(file.Body as Buffer);

        if (q.width || q.height) {
            sharpConfig = sharpConfig.resize(q.width, q.height, {
                withoutEnlargement: true
            });
        }

        const buffer = await sharpConfig.toBuffer();

        await s3PutObject(bucketTmp, newKey, buffer, {
            CacheControl: 'max-age=31536000',
            Tagging: 'ImageCache=true'
        });

        response.body = buffer.toString('base64');
    }

    response.status = 200;
    response.bodyEncoding = 'base64';
    response.headers['content-type'] = [
        {
            key: 'Content-Type',
            value: 'image/' + ext === 'jpg' ? 'jpeg' : ext
        }
    ];

    return response;
};

Upvotes: 3

Views: 3080

Answers (1)

misantronic
misantronic

Reputation: 1211

Ok, I just found out, that the an origin response can have a timeout up to 30s. So I can increase it.

Upvotes: 1

Related Questions