No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Manejando un Pool de conexiones

7/27
Recursos

Aportes 19

Preguntas 16

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Un pool de conexiones es un conjunto limitado de conexiones a una base de datos, que es manejado por un servidor de aplicaciones de forma tal, que dichas conexiones pueden ser reutilizadas por los diferentes usuarios.

Manejando un Pool de conexiones

Hay un problema con getConnection. El problema es que cada vez que llamamos a getConnection, lo que hacemos internamente en el codigo es llamar y llamar y llamar, es decir hacer request continuamentes, eso esta mal porque puede sobrecargar el servidor de request. Entonces, esto es un problema porque por cada request se crea una negociacion con la db, se tarda 20ms o mas, y asi vamos saturando el servidor. La solucion es usar pool.

Sin un pool, yo deberia cerrar las conexiones manuelament.e

Que es un pool? Un pool de conexiones es un conjunto limitado de conexiones a una base de datos, que es manejado por un servidor de aplicaciones de forma tal, que dichas conexiones pueden ser reutilizadas por los diferentes usuarios. Un pool optimiza

Lo que hace el pool es sencillamente es ser un mediador entre las bases de datos y el cliente. Entonces a medida que los clientes empiecen a hacer consultas, la aplicacion de manera asincrona conectara con el pool y el pool se encargara tanto de abrir o cerrar conexiones para que la informacion siga trabajando de manera eficiente. Pero un pool es mucho mas inteligente que eso, ya que permite REUTILIZAR DATA QUE OTROS CLIENTES YA ACCEDIERON, CLARO SIEMPRE Y CUANDO LA DATA A REUTILIZAR SEA LA MISMA QUE ESOS CLIENTES NECESITABAN , y a su vez lograremos que los servidores no se saturen y nuestra app en el background trabajara con las consultas, y asi evitara un problema en el proceso.

Comparto mi código para el create, delete y update para las categorías.

users.service.js

const boom = require('@hapi/boom');

const pool = require('../libs/postgres.pool');

const getConnection = require('../libs/postgres');

class UserService {
  constructor() {
    this.users = [];
    this.pool = pool;
    this.pool.on('error', (err) => console.error(err));
  }

  async create(data) {
    return data;
  }

  async find() {
    const query = 'SELECT * FROM tasks';
    const rta = await this.pool.query(query);
    return rta.rows;
  }

  async findOne(id) {
    return { id };
  }

  async update(id, changes) {
    return {
      id,
      changes,
    };
  }

  async delete(id) {
    return { id };
  }
}

module.exports = UserService;

Ese pool es básicamente un singleton

la verdad en este curso en específico estoy teniendo muchos problemas con el código, estoy recibiendo errores como this.pool.query(query);

Mi resumen!

Ahora,mostrare como el codigo ha cambiado:

//libs/postgres.pool.js

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

  const pool = new Pool({
    host: 'localhost',
    port: 5432,
    user: 'nico',
    password: 'admin123',
    database: 'my_store'
});

//Fijate que el codigo ha cambiado, ahora el trabajar con el driver pg no se basa en ser una funcion, sino mas bien un objeto. y desde aca empezamos a trabajar con pool, fijate las variables... Ahora tambien se puede aprecier que el codigo es mas simple.

module.exports = pool;
// services/product.service.js  

//En este archivo elimine unas lineas de codigo para que sea mas facil de entender y asi no ver todo el codigo que no importa

class ProductsService {

  constructor(){
    this.products = [];
    this.generate();
    **this.pool = pool
    this.pool.on('error', (err) => console.error(err)) //1)**
  }

  async find() {
    const query = 'SELECT * FROM tasks'
    const rta = await this.pool.query(query);
    return rta.rows; //2) Accedemos a pool y especifcamente le passamos el query que este metodo necesita
  }

  1. El punto 1) es el mas importante, por que? Bueno, porque lo que hace es ser las funcion prinicpal de pool, es decir, sabiendo que pool lo que hace es NO LLAMAR continuamente a una funcion y lograr no sobresaturar el servidor/db, la manera en la que lo logramos es poner a POOL en el constructor. Por que? Bueno simplemente porque lo que esto nos permite es justamente llegar a pool desde los diferentes servicios, es decir, el acceso a pool es compartido!, Por lo tanto, al estar pool en el constructor, y nosotros tener dentro de la class ProductService muchos servicios, como find,findOne,etc lo que hacemos es LLAMAR A POOL UNA SOLA VEZ DESDE EL COSNTRUCTOR, Y LUEGO CON CADA SERVICIO COMO FIND,FINDONE,ETC Le pasamos el query necesario! ESO ES LO QUE HACE QUE POOL SEA TAN EFICIENTE!

Por lo tanto, lo que podemos entender es que: la class ProductService crea un canal con el servidor con el mediador pool. Y cada servicio dentro de la clase genera su consulta adecuada. Por lo tanto, Otro archivo como no se… category.service, accedera a pool y abrira otro canal y accedera con su servicios por otro canal.


Yo no agregue un nuevo script para manejar el pool de conexiones, por el contrario lo agregué al que ya tenia

Una vez realizado esto, modifique todo mi servicio para que usara el connection pool con promesas:

Tuve que hacer ciertas modificaciones porque ahora mis campos de producto cambiaron:

Pero una vez realizados estos ajustes pude usar todos mis endpoints hacia la base de datos de forma fluida

Hasta este punto por cada llamado a de un servicio a la base de datos se esta creando una conexión, de implementarse asi en todos los servicios se estarian creado multiples conexiones y esto no seria una buena practica.

Aquí entra la interfaz de Pool de conexiones que permite usar varias conexiones en toda la aplicación pero reutilizando la primera.

Del modulo de pg admin importaremos el modulo de Pool y utilizaremos la siguiente configuración en un nuevo archivo dentro de libs llamado postgres.pool.js:

Ahora se debe implementar en los servicios, donde se remplazara la conexión que anteriormente se tenia de la siguiente manera.

Use un patron singleton para asegurarme de solo usar una instancia de la conexion al pool

import { Pool as PostgresClient } from 'pg';

export default class PostgressPool {
  private static connection: PostgresClient | null = null;

  private constructor() {}

  public static getInstance(): PostgresClient {
    if (!PostgressPool.connection) {
      PostgressPool.connection = new PostgresClient({
        host: 'localhost',
        port: 5432,
        user: 'root',
        password: 'root',
        database: 'my_store'
      });
      console.log('Connected successfully');
    }
    return PostgressPool.connection;
  }

  public async query(request: string) {
    try {
      const db = PostgressPool.getInstance();
      return await db.query(request);
    } catch (error) {
      console.log(error);
    }
  }
}
No entiendo por que se puseo this.pool = pool en el constructor, no podria haberse llamado el pool directamente en cada metodo de la class.

Corrijanme si me equivoco, pero creo que una manera eficiente de colocar el pool y el pool.on("error") es crear una clase base e extenderla en los demas servicios:

export abstract class Services implements IServices {
	pool: Pool;
	constructor() {
		this.pool = pool;
	}
}

Y podrias extenderlas de la siguiente manera (utilizando typescript):

class ArticlesServices extends Services {
	constructor(
		public perro = "perrito",
	) {
		super();
	}
	
	async create() {

	}

	async find() {

	}

	async findOne(slug: string) {

	}

	async update() {

	}

	async delete() {

	}
}
``

Muy agradecido con Platzi, he aprendido bastante con los cursos. Muchas gracias!

Manejando un Pool de conexiones
Modificamos el archivo creado en libs, y modificamos Client por Pool

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

  const pool = new Pool({
    host: "localhost",
    port:5432,
    user:"juancacode",
    password:"admin123",
    database:'my_store_db'
  })

  module.exports = pool;

Llamamos en nuestro servicio
const pool = require(’…/libs/postgres.pool’);

modificamos el constructor

class ProductsService {
  constructor() {
    this.products = [];
    this.generate();
    this.pool = pool;
    this.pool.on('error',(err)=>console.error(err));
  }

lo aplicamos a la función

async find() {
    const query = "SELECT * FROM tasks";
    const res = await this.pool.query(query);
    return res.rows;
  }

Me gustaria que se brinde una solucion a como conectar los servicios a la Base de Datos. Me parece muy mal que se indique al alumno “realicen todas las demas conexiones a los servicios” teniendo una minima guia con la tabla tasks.

Creo que pooling esta relacionado con los websockets, creo que son Event emitters incluso lo de > this.pool.on(‘error’, cb)
es algo que se usa en webSockets si saben Socketio sabrán a lo que me refiero.

Mi update:

async update(id, changes) {
try {
const keys = Object.keys(changes);
const values = Object.entries(changes).map((b) => b[1]);
const updates = keys.map((key, index) => ${key}=$${index + 1}).join();
const query = UPDATE users SET ${updates} WHERE id = $${ keys.length + 1 };
await this.pool.query(query, […values, id]);
return {
id,
…changes,
};
} catch (error) {
return ‘Error on updating’ + error;
}
}

Super, ya quedo el pool en cada service