node-postgres icon indicating copy to clipboard operation
node-postgres copied to clipboard

Passing the same Client in multiple functions

Open spimou opened this issue 6 years ago • 1 comments

I am using pg 7.4.2 (also express 4.16.3 and node 8.11.1), and I have to use Clients, because of transactions. This is my best of coming up with a general function that executes queries.

Since "You should be creating the client for each request....then closing it ....when you're done." "If you're creating the client manually, once at startup then if it ever has an issue ...your app will never recover. It won't auto-reconnect or recreate itself. ...you should be tying the creation of clients to the lifecycle of their use. If it's tied to a request, ....then create the client in that function and dispose of it when that piece is done. " from

My function, either creates a Client on the spot to execute a query and then disconnects that Client or it can get an already existing Client as an argument, execute a query and disconnect that Client only if there is an error.

This is the function

let queryCounter=0;
const query = (text, params, client) => {
  if (!client) {
    console.log('NEW');
    const client = new Client(clientobj);
    return client.connect().then(() => {
       queryCounter+=1; client.customid=queryCounter; client.customname='query';
        console.log('client in query if -- ', client.customid, client.customname);
        return client.query(text, params)
        .then(res => {
          console.log('then in if');          
          client.end().then(() => console.log('query if then disconnected -- ', client.customid, client.customname ));
          return res;
        })
        .catch(e => {
          client.end().then(() => console.log('query if catch disconnected -- ', client.customid, client.customname ));
          return e;
        })
    })// client connect then
  } //IF
  else {
    console.log('EXISTING');
    console.log('client in query else -- ', client.customid, client.customname);
    return client.query(text, params)
    .then(res => {
      console.log('then in else');      
      return res;
    })
    .catch(e => {
      client.end().then(() => console.log('query else catch disconnected -- ', client.customid, client.customname ));
      return e;
    })
  } //ELSE
} //query

and I can call it either like

query('UPDATE user SET name = ($1)', [name], false)
        .then(res=>{//you know the drill

or like

let otherCounter=0;
const otherFunction= () => {
  return new Promise((resolved, rejeted)=>{
  let client = new Client(clientobj);
      client.connect().then(() => {
        otherCounter+=1; client.customid=otherCounter; client.customname='otherFunction';
        console.log('client in otherFunction-- ', client.customid, client.customname);
        query('UPDATE user SET name = ($1)', [name], client)
        .then(res=>{ 
          console.log('otherFunction res -- ', res)
          client.end().then(() => console.log('otherFunction then disconnected -- ', client.customid, client.customname )));
        })
.catch(error => {
        rejeted('otherFunction error', error);
        client.end().then(() => console.log('otherFunction catch disconnected -- ', client.customid, client.customname ));
      });
  }) 
};

Everything looks fine and the console logs are what they should be. I would really appreciate your opinion on this . Is this proper Client management, or I am missing something, leaking Clients? I am a newbie and there is big chance I am doing something wrong.

Thank you for your time.

spimou avatar Jun 01 '18 17:06 spimou


const { Client } = require('pg');
const clientConfig = { /* ... your client configuration ... */ };

// Function to create a new client and connect
function createClient() {
  const client = new Client(clientConfig);
  return client.connect().then(() => client);
}

// Function to execute a query
function executeQuery(text, params, client) {
  const shouldCloseClient = !client;

  if (shouldCloseClient) {
    // Create a client if one isn't provided
    client = createClient();
  }

  return client.then(client => {
    return client.query(text, params)
      .then(res => {
        if (shouldCloseClient) {
          client.end();
        }
        return res;
      })
      .catch(e => {
        if (shouldCloseClient) {
          client.end();
        }
        throw e; // Re-throw the error after handling it
      });
  });
}

// Usage example with a new client
executeQuery('UPDATE user SET name = $1', [name])
  .then(res => {
    // Handle result
  })
  .catch(err => {
    // Handle error
  });

// Usage example with an existing client
const client = createClient();
executeQuery('UPDATE user SET name = $1', [name], client)
  .then(res => {
    // Handle result
    client.end();
  })
  .catch(err => {
    // Handle error
    client.end();
  });

ljluestc avatar Dec 23 '23 21:12 ljluestc