2

I am using Knex.js to insert values from an array into a PostgreSQL database. The problem I keep running into is that Knex will hang after inserting rows in the database.

I've been struggling with this for several hours, and have tried a variety of solutions, including Get Knex.js transactions working with ES7 async/await, Make KnexJS Transactions work with async/await, and Knex Transaction with Promises.

No matter which flavor I try, I come back to the hang. I'm pretty sure I'm missing something obvious, but it's possible I haven't had enough coffee.

Here's my test code:

const testArray = [
  {line: 'Canterbury Tales'},
  {line: 'Moby Dick'},
  {line: 'Hamlet'}
];

const insertData = (dataArray) => {
  return new Promise( (resolve, reject) => {
    const data = dataArray.map(x => {
      return {
          file_line: x.line
      };
    });

    let insertedRows;

    db.insert(data)
      .into('file_import')  
      .then((result) => {
        insertedRows = result.rowCount;
        resolve(insertedRows);
      })
  });
}

const testCall = (b) => {
  insertData(b).then((result) => {
    console.log(`${result} rows inserted.`);
  })
}

testCall(testArray);

This returns the following:

3 rows inserted.

EDIT: Updating with solution Thanks to @sigmus, I was able to get this working by adding db.destroy(). Here's the updated code block, fully functional:

const testArray = [
  {line: 'Canterbury Tales'},
  {line: 'Moby Dick'},
  {line: 'Hamlet'}
];

const insertData = (dataArray) => {
  return new Promise( (resolve, reject) => {
    const data = dataArray.map(x => {
      return {
          file_line: x.line
      };
    });

    let insertedRows;

    db.insert(data)
      .into('file_import')  
      .then((result) => {
        insertedRows = result.rowCount;
        resolve(insertedRows);
      })
      .finally(() => {              
        db.destroy();
      });
  });
}

const testCall = (b) => {
  insertData(b).then((result) => {
    console.log(`${result} rows inserted.`);
    process.exit(0);
  })
}

testCall(testArray);
paulmiller3000
  • 436
  • 8
  • 24
  • Would it help if you add a ```process.exit(0);``` right after ```console.log(`${result} rows inserted.`);```? – sigmus Jul 19 '19 at 19:14
  • @sigmus That does allow the app to end, thank you! However, I wonder if there's still a better way? I tried `process.exitCode = 0` to exit naturally per https://stackoverflow.com/a/37592669/1575022, but the app still hangs. So, `process.exit(0)` feels like a stopgap. – paulmiller3000 Jul 20 '19 at 10:24
  • 1
    Without process.exit, does it take a long time to exit or it never exits at all? Maybe it's a connection pool issue, try using ```destroy``` like explained here: https://knexjs.org/#Installation-pooling – sigmus Jul 20 '19 at 10:34
  • @sigmus, genius! I didn't even think to check that. If you re-post as the answer, I'll accept and update original post with solution. Thank you! – paulmiller3000 Jul 20 '19 at 12:35
  • Re-posted as an answer, cheers. – sigmus Jul 22 '19 at 09:54

1 Answers1

3

If you add process.exit(0); right after console.log(`${result} rows inserted.`); the script should exit.

It may be the case it's a connection pool issue, try using destroy like explained here: https://knexjs.org/#Installation-pooling

sigmus
  • 2,987
  • 3
  • 23
  • 31