TransWikia.com

AWSのLambdaからLambdaを呼び出したときに、呼び出し先のLambdaからのレスポンスを待たずに呼び出し元のLambdaが処理終了してしまう

スタック・オーバーフロー Asked by masaru.morita on November 17, 2021

PollyでMP3を作成してからS3にアップロードし、URLを返すLambdaを、別のLambdaから呼び出しているのですが、呼び出し先のレスポンスを待たずに呼び出し元のLambdaが先に完了してしまします。呼び出し先のLambdaによるMP3作成は、呼び出し元が完了後に完了する動きになってしまっています。

呼び出し先のLambdaのレスポンスを待ってから、呼び出し元のLambdaを完了させるにはどうすればよいでしょうか。

■呼び出し元のLambda

var lambda = new AWS.Lambda({apiVersion: '2015-03-31'})
exports.handler = function(event, context, callback){
    res = invokeCreateMp3()
    console.log(res) //undefinedになる
}

function invokeCreateMp3(name, sec) {
    lambda.invoke({
        FunctionName: 'create_mp3_for_timer',
        InvocationType: 'RequestResponse',
        Payload: '{ "name":"kana", "sec":3 }',
    }, function(error, data) {
        if (error) {
            console.log("error:" + error)
        } else {
            console.log("response:" + data)
        }
    });
}

■呼び出し先のLambda

var polly = new AWS.Polly({apiVersion: '2016-06-10'});
var s3 = new AWS.S3({apiVersion: '2006-03-01'});

exports.handler = function(event, context, callback) {
    var url = createMp3(event.name, event.sec);
    var res = {
        "statusCode": 200,
        "headers": { "Additional-Headr1": "1234" },
        "body": JSON.stringify({"response":"response", "event":event, "url":url}),
    };

    callback(null, res);
};

function createMp3(name, sec) {
    var ssml = '<speak><break time="' + sec +'s" />' + name +'タイマーは終わりです。</speak>';
    var buket = 'mp3_buket';
    var key = name + '_' + sec + 's.mp3';
    var url = 'https://s3-ap-northeast-1.amazonaws.com/' + buket + '/' + key;

    let speechParams = {
        OutputFormat: 'mp3',
        VoiceId: 'Mizuki',
        Text: ssml,
        SampleRate: '22050',
        TextType: 'ssml'
    };


    polly.synthesizeSpeech(speechParams).promise().then((data) => {
        console.log(data);           // successful response
        // s3にPutする用のパラメータ
        var s3Params = {
            ACL: 'public-read', //S3権限
            Bucket: buket,
            Key: key,
            ContentType: 'audio/mp3',
            Body: new Buffer(data.AudioStream) // AudioStreamの取得
        };
        // s3にputする
        s3.putObject(s3Params, (err) => {
            if (err) {
                console.log(err);
            } else {
                console.log('Success');
            }
        });
    }, (error) => {
        console.log("Failure!", error);
    });
    return url;
}

2 Answers

呼び出し元がコールバックを待つ実装になっていないようです。
動作確認まではできていないのですが、こんな感じに修正すれば同期的に実行できるのではないでしょうか。

var lambda = new AWS.Lambda({apiVersion: '2015-03-31'})
exports.handler = async function(event, context, callback){
    res = await invokeCreateMp3()
    console.log(res) //undefinedになる
}

async function invokeCreateMp3(name, sec) {
    try {
        const data = await lambda.invoke({
            FunctionName: 'create_mp3_for_timer',
            InvocationType: 'RequestResponse',
            Payload: '{ "name":"kana", "sec":3 }',
        }).promise();
        console.log("response:" + data);
        return data;
    } catch (error) {
        console.log("error:" + error);
        return error;
    }
}

Answered by Bladean Mericle on November 17, 2021

nodejsにあまり詳しくないので、外しているかもしれませんが、まずinvokeCreateMp3は非同期で動作すると思うので、promiseを返すなどして終了待機をする必要があるのでは?
同様にcreateMP3の部分も。

putObjectもpromiseを使う必要があるかと思います。

Answered by Hattori Makoto on November 17, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP