Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Awaiting on pgcursor.close may never resolve #2642

Open
FreeSlave opened this issue Oct 27, 2021 · 0 comments
Open

Awaiting on pgcursor.close may never resolve #2642

FreeSlave opened this issue Oct 27, 2021 · 0 comments
Labels

Comments

@FreeSlave
Copy link

FreeSlave commented Oct 27, 2021

I'm using pgcursor on Amazon Aurora PostgreSQL. If connection is terminated due to serverless scale event timeout, the promise returned by close methods of the Cursor never resolves. Probably because it never gets the readyForQuery event https://github.com/brianc/node-postgres/blob/master/packages/pg-cursor/index.js#L218

I made an assumption that the same can happen on regular postgresql if we manually abrupt the connection from the server side (terminating connection due to administrator command) while cursor is open and I was able to replicate it with this code (Obviously you need to fill configure clients with your settings):

const { Client } = require('pg')
const PgCursor = require('pg-cursor')

const client = new Client({
    user: process.env.POSTGRES_USER,
    host: process.env.POSTGRES_HOST,
    database: process.env.POSTGRES_DATABASE,
    password: process.env.POSTGRES_PASSWORD,
    port: +(process.env.POSTGRES_PORT || 5432),
})
client.on('error', function(err: Error) {
    console.error('In error handler:', err)
})

const terminatingClient = new Client({
    user: process.env.POSTGRES_USER,
    host: process.env.POSTGRES_HOST,
    database: process.env.POSTGRES_DATABASE,
    password: process.env.POSTGRES_PASSWORD,
    port: +(process.env.POSTGRES_PORT || 5432),
})
terminatingClient.on('error', function(err: Error) {
    console.error('terminatingClient In error handler:', err)
})

function terminatePostgresConnectionQuery(processID: number, db: string) {
    return `SELECT pg_terminate_backend(pid) FROM 
    pg_stat_activity WHERE 
    pid = ${processID}
    AND datname = '${db}';`
}

;(async() => {
    try {
        await client.connect()
        await terminatingClient.connect()

        const pgCursor = (client.query(
            new PgCursor(`SELECT NOW()`)
        ))
        console.log('Process id:', client.processID)
        await terminatingClient.query(
             terminatePostgresConnectionQuery(client.processID, process.env.POSTGRES_DATABASE ?? 'db'))

        console.log('Made terminatingQuery')
        await pgCursor.close()
        console.log('cursor closed')
    }
    catch(err) {
        console.error('In catch: ', err)
    } finally {
        try {
            await client.query('SELECT NOW()')
        } catch(err) {
            console.error('Error in finally', err)
        }
        console.log('Exiting')
        await client.end()
        await terminatingClient.end()
    }
})()

Here we create two connections. One is used to create a cursor and make a select query. Another is used to kill the first one via pg_terminate_backend.

It never reaches console.log('cursor closed').

@charmander charmander added the bug label Oct 31, 2021
adam-nielsen added a commit to adam-nielsen/node-postgres that referenced this issue Sep 2, 2022
adam-nielsen added a commit to adam-nielsen/node-postgres that referenced this issue Sep 2, 2022
adam-nielsen added a commit to adam-nielsen/node-postgres that referenced this issue Sep 2, 2022
This isn't a real fix because it delves into the connection's private state,
but it does illustrate one possible solution.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants