4

UPDATE/SOLVED ... the problem was that pgpass plugin was looking for $HOME/.pgpass, and $HOME wasn't defined on lambda, causing failure of join(undefined, '.pgpass'). Not really worth crediting myself with an answer for that ....

I have the following test code in a lambda handler (compiled from typescript):

const db = new Pool()
const {rows} = await db.query('select 1 as x')
console.log('rows', JSON.stringify(rows))

The connection is created via PGHOST PGPORT PGUSER PGDATABASE in the environment. I know the configuration is "almost right" because the first time I tried it I got:

{"errorMessage":"error: no pg_hba.conf entry for host \"10.1.1.249\", user \"foo\", database \"bar\", SSL off\n at Connection.parseE (/var/task/handler.js:9209:11)\n at Connection.parseMessage (/var/task/handler.js:9034:19)\n at Socket. (/var/task/handler.js:8777:22)\n at emitOne (events.js:96:13)\n at Socket.emit (events.js:188:7)\n at readableAddChunk (_stream_readable.js:176:18)\n at Socket.Readable.push (_stream_readable.js:134:10)\n at TCP.onread (net.js:547:20)"}

That seemed hopeful. I changed the postgres config to allow from the subnet, and tried again. However, now I get:

2018-02-06 18:14:21.183 (-05:00)    76761ca5-0b93-11e8-8783-a74d098c9f4a    select
2018-02-06 18:14:21.202 (-05:00)    76761ca5-0b93-11e8-8783-a74d098c9f4a    TypeError: Path must be a string. Received undefined
    at assertPath (path.js:7:11)
    at Object.join (path.js:1211:7)
    at Object.module.exports.getFileName (/var/task/handler.js:32434:16)
    at module.exports (/var/task/handler.js:32355:23)
    at Connection.<anonymous> (/var/task/handler.js:31255:9)
    at emitOne (events.js:96:13)
    at Connection.emit (events.js:188:7)
    at Socket.<anonymous> (/var/task/handler.js:8781:12)
    at emitOne (events.js:96:13)
    at Socket.emit (events.js:188:7)
END RequestId: 76761ca5-0b93-11e8-8783-a74d098c9f4a

What is going on? It seemed as if it had got to the database and connected the first time... Now it fails on the query. Is there some option I should be using?

smac2020
  • 9,637
  • 4
  • 24
  • 38
shaunc
  • 5,317
  • 4
  • 43
  • 58
  • 1
    Kindly show your handler source code. Since we cannot see when/how you connect to the database relative to your handler function. Typescript is fine. – Noel Llevares Feb 07 '18 at 15:21
  • @dashmug Handler just wraps the lines posted. The connection is handled implicitly on call to query. (See https://github.com/brianc/node-pg-pool#your-new-favorite-helper-method) All the parameters are in the environment. – shaunc Feb 07 '18 at 23:57
  • Have tried `console.log(process.env.PGHOST)` to see if the environment variables are set? – Noel Llevares Feb 08 '18 at 03:17
  • Yes ... printed out process.env and it includes PGHOST, etc. PGHOST is IP address (not hostname), but this should work. – shaunc Feb 09 '18 at 06:28
  • Maybe you should reconsider and simply just don't use a connection pool. They're useless on AWS Lambda anyway. – Noel Llevares Feb 09 '18 at 12:14
  • 1
    You should credit yourself for the answer. Solved my problem. – asr9 Jan 09 '19 at 22:20
  • Until it's merged, you can use this fork of pgpass: https://github.com/beekeeper-studio/pgpass/tree/blank-home. If you use yarn you can add a resolutions section: "resolutions": { "pg/pgpass": "beekeeper-studio/pgpass#blank-home" }, – Matthew Rathbone May 07 '20 at 22:31

1 Answers1

1

First, you are not calling pool.connect to acquire a client from the pool.

Second, the current Node.js runtime 6.10 on AWS Lambda does not support async functions. (Unless you transpile your code down to ES5 using Babel directly or some other boilerplate that uses Babel such as es2017-lambda-boilerplate)

Having said that, you'll have to use either callbacks or promises (then/catch). For example:

const {Pool} = require("pg");

const db = new Pool({
  host: "localhost",
  user: "database-user",
  // ... rest of config options
});

db.connect((err, client, release) => {
  if (err) {
    console.error("Error acquiring client.", err.stack);
  } else {
    client.query("SELECT 1 AS x", (err, result) => {
      release();
      if (err) {
        console.error("Error executing query.", err.stack);
      } else {
        console.log(result.rows);
      }
    })
  }
})
Khalid T.
  • 10,039
  • 5
  • 45
  • 53
  • (1) no need to call connect -- will automatically connect on `pool.query()` (2) In fact, using typescript so async isn't an issue (and would have caused syntax error if it were). Since it attempted connection, these issues aren't the problem. The error seems to be that wrapper is asking for a filename from a tcp socket which has no filename. (But why?) – shaunc Feb 07 '18 at 23:55