AWS- लैम्ब्डा में, मैं DynamoDB तालिका से डेटा पुनर्प्राप्त करने और API गेटवे के लिए एक पोस्ट अनुरोध करने के लिए डेटा का उपयोग करने के लिए कॉल कर रहा हूं। मैंने DynamoDB से डेटा पुनर्प्राप्त करने के लिए Async/प्रतीक्षा का उपयोग किया। हालांकि, एपीआई गेटवे के लिए एक पोस्ट अनुरोध करते समय Https.request को कॉल नहीं किया जा रहा है।

मैं NodeJs और लैम्ब्डा के लिए नौसिखिया हूँ, समाधान पाने के लिए आपकी मदद की सराहना करता हूँ।

मैंने बिना किसी किस्मत के प्रॉमिस को लागू करने की कोशिश की। अगर मैं Async/प्रतीक्षा को हटा देता हूं तो Https.request कॉल बिना किसी समस्या के काम कर रहा है। लेकिन पोस्ट अनुरोध करने के लिए https.request के लिए डेटा उपलब्ध नहीं है (async कॉल के कारण)।

// Dynamo DB Params
var {promisify} = require('util');
var AWS = require('aws-sdk');
var dynamoDB  = new AWS.DynamoDB.DocumentClient();
var dynamoDBGetAsync = promisify(dynamoDB.get).bind(dynamoDB );
var https = require('https');

exports.handler = async function(event,context) {
    let probID = JSON.stringify(event.ID);
    probID = probID.replace(/"/g, '');      

    let params = {
        TableName : '<dummy_table>',
        Key:{
            'Server':<serverid>,
            'Service':'process2'
        }
    };

    //fetching the details from Dynamo DB 
    var dataResult= await dynamoDBGetAsync(params);   

    var obj;   
    var message = 'Sample Message';
    functionCall(dataResult,callback => {
        obj = JSON.parse(callback);
    });
}

function functionCall(data,result) {
// Options and headers for the HTTP request
    var options = {
        host: 'dummy.execute-api.us-east-1.amazonaws.com',
        port: 443,
        path: '/dev/test',
        method: 'POST',
        headers: {
            'Accept':'*/*',
            'cache-control':'no-cache',
            'Content-Type': 'application/json'
        }
    };
    const body= "{\"msg\": "+ data + "\"}";
    console.log('BODY.....:'+body);      //able to see this comment in console

    let req = https.request(options, (res) => {     // This is not getting invoked and cannot see below comment in console
        console.log('IN HTTPS REQUEST.....');
        var responseString = '';
        console.log("statusCode:" + res.statusCode);

        res.setEncoding('UTF-8');
        // Collect response data as it comes back.
        res.on('data', function(data) {
            responseString += data;

        });

        res.on('end', function() {
            result(responseString);
        });
    });

    // Handler for HTTP request errors.
    req.on('error', function(e) {
        console.error('HTTP error: ' + e.message);
        result('Request completed with error(s).');
    });

    req.write(body);
    req.end();
}
0
Ramana Murty Kora 30 अप्रैल 2019, 15:10

1 उत्तर

सबसे बढ़िया उत्तर

कुछ संभावित समस्याएं हैं लेकिन मेरे लिए सबसे खास बात यह है कि आप प्रोग्रामिंग शैलियों को गलत तरीके से मिला रहे हैं।

आपने हैंडलर को एसिंक्स फ़ंक्शन के रूप में घोषित किया है जो ठीक है। लेकिन async फ़ंक्शन के अंदर आप एक क्लासिक निरंतरता-शैली फ़ंक्शन कॉल के साथ एक प्रतीक्षा योग्य कॉल को मिला रहे हैं जिसका आप ठीक से इंतजार नहीं कर रहे हैं।

क्या हो रहा है कि आपका लैम्ब्डा पहले भाग (डायनेमो पर कॉल) को निष्पादित करता है और फिर रनटाइम वास्तव में आपकी दूसरी निरंतरता-शैली फ़ंक्शन कॉल को पूरा करने से पहले निष्पादन समाप्त करता है।

एक उपाय यह है कि अपने https अनुरोध को एक वादे में लपेटें और उस पर लैम्ब्डा हैंडलर के शरीर में प्रतीक्षा करें:

// Dynamo DB Params
const {promisify} = require('util');
const AWS = require('aws-sdk');
const dynamoDB  = new AWS.DynamoDB.DocumentClient();
const dynamoDBGetAsync = promisify(dynamoDB.get).bind(dynamoDB );
const https = require('https');

exports.handler = async function(event,context) {
    let probID = JSON.stringify(event.ID);
    probID = probID.replace(/"/g, '');      

    let params = {
        TableName : '<dummy_table>',
        Key:{
            'Server':<serverid>,
            'Service':'process2'
        }
    };

    //fetching the details from Dynamo DB 
    let dataResult= await dynamoDBGetAsync(params);   

    const message = 'Sample Message';
    let jsonResult = await functionCall(dataResult);
    let obj = JSON.parse(jsonResult);
    // presumably you want to return something here (not sure if obj or something else)
    return obj;
}

function functionCall(data) {
    // Options and headers for the HTTP request
    const options = {
        host: 'dummy.execute-api.us-east-1.amazonaws.com',
        port: 443,
        path: '/dev/test',
        method: 'POST',
        headers: {
            'Accept':'*/*',
            'cache-control':'no-cache',
            'Content-Type': 'application/json'
        }
    };
    const body= "{\"msg\": "+ data + "\"}";
    console.log('BODY.....:'+body);

    // make this function awaitable by returning a promise
    return new Promise((resolve, reject) => {
      let req = https.request(options, (res) => {
        console.log('IN HTTPS REQUEST.....');
        let responseString = '';
        console.log("statusCode:" + res.statusCode);

        res.setEncoding('UTF-8');
        // Collect response data as it comes back.
        res.on('data', function(data) {
          responseString += data;
        });

        res.on('end', function() {
          // complete the promise successfully
          resolve(responseString);
        });
      });

      req.on('error', function(e) {
        console.error('HTTP error: ' + e.message);
        // complete the promise with error (will throw if awaited)
        reject('Request completed with error(s).');
      });

      req.write(body);
      req.end();
    });
}

वैसे - async/wait का उपयोग करके DynamoDB के साथ काम करने के लिए आपको वास्तव में वादे की आवश्यकता नहीं है। DynamoDB क्लाइंट के पास उन वादों के लिए अंतर्निहित समर्थन है जिनकी आप प्रतीक्षा कर सकते हैं। अपने ऑपरेशन के लिए बस .promise() पर कॉल करें और उस पर प्रतीक्षा करें। उदाहरण के लिए, आप बस लिख सकते हैं:

let dataResult = await dynamoDB.get(params).promise();
1
Mike Dinescu 30 अप्रैल 2019, 20:56