Можете ли вы поддерживать соединение PostgreSQL в рабочем состоянии из Next.js API?

#node.js #postgresql #next.js #serverless #node-postgres

#node.js #postgresql #next.js #без сервера #узел-postgres

Вопрос:

Я использую Next.js для моего сайд-проекта. У меня есть база данных PostrgeSQL, размещенная на ElephantSQL. Внутри Next.js проект, у меня настроен GraphQL API, использующий пакет apollo-server-micro.

Внутри файла, в котором настроен API GraphQL (/api/graphql), я импортирую вспомогательный модуль базы данных. Внутри этого я настраиваю соединение с пулом и экспортирую функцию, которая использует клиента из пула для выполнения запроса и возврата результата. Это выглядит примерно так:

 // import node-postgres module
import { Pool } from 'pg'

// set up pool connection using environment variables with a maximum of three active clients at a time
const pool = new Pool({ max: 3 })

// query function which uses next available client to execute a single query and return results on success
export async function queryPool(query) {
    let payload

    // checkout a client
    try {
        // try executing queries
        const res = await pool.query(query)
        payload = res.rows
    } catch (e) {
        console.error(e)
    }

    return payload
}
  

Проблема, с которой я сталкиваюсь, заключается в том, что кажется, что Next.js API не (всегда) поддерживает соединение, а скорее открывает новое (либо для каждого подключенного пользователя, либо, возможно, даже для каждого запроса API), что приводит к быстрому исчерпанию соединений в базе данных.

Я считаю, что то, чего я пытаюсь достичь, возможно, например, в AWS Lambda (установив для context.callbackWaitsForEmptyEventLoop значение false).

Очень возможно, что у меня нет правильного понимания того, как работают бессерверные функции, и это может быть вообще невозможно, но, возможно, кто-то может предложить мне решение.

Я нашел пакет под названием serverless-postgres, и мне интересно, сможет ли это решить проблему, но я бы предпочел использовать пакет node-postgres, поскольку он имеет гораздо лучшую документацию. Другим вариантом, вероятно, было бы полностью отказаться от интегрированной функциональности API и создать выделенный серверный сервер, который поддерживает соединение с базой данных, но, очевидно, это будет последнее средство.

Комментарии:

1. хороший вопрос, есть какое-нибудь хорошее решение? Br

2. @user1665355 к сожалению, нет. существует бессерверный модуль mysql, который должен решить эту проблему для соединений с базой данных MySQL, но, к сожалению, для Postgres нет аналогичного модуля. я действительно надеюсь, что кто-нибудь создаст его в будущем, но до тех пор нам придется использовать второй выделенный сервер подключения к БД.

Ответ №1:

Я еще не проводил стресс-тестирование, но похоже, что mongodb next.js например, решает эту проблему путем подключения к базе global данных в вспомогательной функции. Важный момент в их примере здесь.

Поскольку pg соединение немного более абстрактно, чем mongodb , похоже, этот подход занимает всего несколько строк для нас pg , энтузиастов:

 // eg, lib/db.js


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

if (!global.db) {
  global.db = { pool: null };
}

export function connectToDatabase() {
  if (!global.db.pool) {
    console.log("No pool available, creating new pool.");
    global.db.pool = new Pool();
  }
  return global.db;
}
  

тогда, например, в нашем маршруте API мы можем просто:

 // eg, pages/api/now


export default async (req, res) => {
  const { pool } = connectToDatabase();
  try {
    const time = (await pool.query("SELECT NOW()")).rows[0].now;
    res.end(`time: ${time}`);
  } catch (e) {
    console.error(e);
    res.status(500).end("Error");
  }
};