Почему мой запрос AWS Lambda node.js mysql не возвращается? - PullRequest
0 голосов
/ 29 января 2019

Я пытаюсь записать некоторые внешние данные в некоторые локальные таблицы.Мы будем перебирать массив, записывая большую часть данных каждого элемента массива в основную таблицу, а остальные - в связанные таблицы, каждый раз заменяя все данные.

Я сократил код доголые кости, чтобы показать мою проблему.DELETE работает нормально, но INSERT запускается только один раз и даже не возвращает.

У меня есть скриншот вывода на https://imgur.com/a/zA6Hz8g.В нем вы можете видеть, что код для DELETE работает нормально (ComQueryPacket отправлен, OkPacket возвращен), но когда он попадает в INSERT, ComQueryPacket отправляется, но ничего не возвращается.И тогда код просто проваливается.

Это приводит к успешной записи первой строки, но последующие строки не записываются.

Я пытался изменить соединение для использования пулов, но это тоже не помогло.

Есть идеи?

var mysql = require('mysql');
var promise = require('promise');

const con = mysql.createConnection({
    <connectionInfo>,
    debug: true
});

function connectToDB() {
    return new promise((resolve, reject) => {
        console.log("IN connectToDB");
        con.connect(function(err) {
            if (err) {
                console.log("ERROR: Could not connect -- " + err);
                reject;
            }
            console.log("Connected!");
            resolve();
        });
    });
}

function deleteExistingMainRow() {
    return new promise((resolve, reject) => {
        var query = "DELETE FROM my_table";
        con.query(query, [],
            function(err, result) {
                if (err) {
                    console.log("ERROR in deleteExistingMainRow: " + err);
                    reject;
                }
                else {
                    console.log("DEBUG: Successful delete of main row");
                    resolve();
                }
            });
    });
}

function writeMainRow(data_row) {
    return new promise((resolve, reject) => {
        console.log("IN writeMainRow");
        var query = 'INSERT INTO my_table SET id = ?';

        con.query(query, [data_row.id],
            function(err, result) {
                console.log("YES we tried to query");
                if (err) {
                    console.log("ERROR in writeMainRow: " + err);
                    reject(err);
                }
                else {
                    console.log("DEBUG: Successful write of main row");
                    resolve();
                }
            });
    });
}

exports.handler = function(event, context) {
    connectToDB().then(function(script) {
        deleteExistingMainRow().then(function(script) {
            var data = [{ "id": 1 }, { "id": 2 }, { "id": 3 }];
            data.forEach(data_row => {
                writeMainRow(data_row).then(function(script) {
                        console.log("DEBUG: Main row written in forEach");
                    },
                    function(err) {
                        if (err) { console.log("ERR"); } process.exit(0);
                    }());
            });
            console.log("DEBUG: Hey we're exiting now");
            con.commit;
            con.end(function(err) {
                console.log("Error on con end: " + err);
            });
            context.done(null, "DONE");
            process.exit(0);
        });
});

};

Ответы [ 3 ]

0 голосов
/ 30 января 2019

попробуйте использовать INSERT INTO table_name (id) VALUES (?);Я знаю, что ваш запрос и вышеупомянутый запрос работает одинаково.Просто попробуйте.

И просто убедитесь, что ваш цикл for работает правильно, отправляя значения в writeMainRow (функцию).Он не будет отображать ошибку, если вы передадите пустое значение и убедитесь, что вы не передаете те же значения в цикле for.И я думаю, что вы должны передать writeMainRow (data_row.id) вместо writeMainRow (data_row) .

Надеюсь, это поможет.И еще одно предложение, если вы обновляете несколько строк, в библиотеке узлов mysql есть опции, например транзакции.Использование этих функций будет более эффективным, и вы можете откатить результат, если столкнетесь с ошибкой.Другой вариант - написать процедуры, в этом случае ваш сервер MySQL будет нести вычисления.

0 голосов
/ 30 января 2019

Причина, по которой ваш код работает не так, как вы ожидаете, заключается в асинхронной природе NodeJS.

Ваш цикл for_each порождает несколько потоков, которые собираются ВСТАВИТЬ данные в вашу базу данных.
Asкак только эти потоки будут запущены, будет выполняться остальная часть кода, начиная с console.log("DEBUG: Hey we're exiting now");

Так что фиксация происходит до того, как будут выполнены все вызовы INSERT, и, что более важно, вы вызываете Process.exit () в вашем коде.Это завершает среду выполнения даже до того, как INSERT может завершиться.Обратный вызов () вместо этого согласно https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html

Обработка нескольких асинхронных записей может выполняться по-разному.Во-первых, как прокомментировал до меня гринет, я настоятельно рекомендую переписать ваш код, используя async / await, чтобы сделать вызов более легким для чтения.Затем вы должны понимать, что каждый вызов writeMainRow будет возвращать свое собственное Обещание, и ваш код должен дождаться завершения ВСЕХ обещаний, прежде чем commit() и callback()

Promise.all(...) выполнят это.для тебя.Смотрите документ на https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

0 голосов
/ 30 января 2019

Всего несколько месяцев назад AWS сделал доступным Node.js v 8.10 в lambda.
Это означает, что вы можете использовать async/await и Promises.
Итак, мы можем изменить код на что-то вроде этого:

exports.handler = async (event, context) => {
     const dbConnection = await connectToDB();

     await deleteExistingMainRow();

     const data = [{ "id": 1 }, { "id": 2 }, { "id": 3 }];

     // use here for...of loop to keep working with async/await behaviour
     for(const data_row of data){
       await writeMainRow(data_row);
     }
}

Кроме того, вы можете переписать свой код, чтобы использовать нативныйPromises или async/await функции.
И, конечно же, логика покрытия в блоке try/catch, я пропустил их для простоты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...