8 changed files with 199 additions and 13 deletions
@ -0,0 +1,20 @@
|
||||
# Как в HR_TG_Bot: тот же Postgres из Postgres_TG_Bots (docker-compose.dev.yml), |
||||
# отдельная база clinic_tests — таблицы приложения не смешиваются с hr_bot_test. |
||||
# |
||||
# Локально (порт 5432 на хосте, как в Postgres_TG_Bots): |
||||
# DATABASE_URL=postgresql://hr_bot_user:hrbot123@localhost:5432/clinic_tests |
||||
# |
||||
# Backend в Docker рядом с HR: хост — container_name Postgres, порт 5432 внутри сети: |
||||
# DATABASE_URL=postgresql://hr_bot_user:hrbot123@hr_postgres_dev:5432/clinic_tests |
||||
# |
||||
# Базу clinic_tests создают один раз (от суперпользователя контейнера): |
||||
# psql "postgresql://hr_bot_user:hrbot123@localhost:5432/postgres" -c "CREATE DATABASE clinic_tests;" |
||||
# |
||||
# Если DATABASE_URL не задан, используются переменные ниже (устаревший сценарий со своим Postgres на 5433). |
||||
# DB_HOST=localhost |
||||
# DB_PORT=5432 |
||||
# DB_NAME=clinic_tests |
||||
# DB_USER=developer |
||||
# DB_PASSWORD=dev_password |
||||
|
||||
DATABASE_URL=postgresql://hr_bot_user:hrbot123@localhost:5432/clinic_tests |
||||
@ -0,0 +1,100 @@
|
||||
/** |
||||
* Database Connection Module |
||||
* PostgreSQL connection pool and utility functions |
||||
*/ |
||||
|
||||
import pg from 'pg'; |
||||
import { getPoolConfig } from './poolConfig.js'; |
||||
|
||||
const { Pool } = pg; |
||||
|
||||
const pool = new Pool(getPoolConfig()); |
||||
|
||||
// Handle pool errors
|
||||
pool.on('error', (err) => { |
||||
console.error('Unexpected pool error:', err.message); |
||||
}); |
||||
|
||||
/** |
||||
* Execute a query with the connection pool |
||||
* @param {string} text - SQL query text |
||||
* @param {Array} params - Query parameters |
||||
* @returns {Promise<pg.QueryResult>} Query result |
||||
*/ |
||||
export async function query(text, params) { |
||||
const start = Date.now(); |
||||
const result = await pool.query(text, params); |
||||
const duration = Date.now() - start; |
||||
|
||||
if (process.env.NODE_ENV === 'development') { |
||||
console.log('Executed query:', { text: text.substring(0, 50), duration, rows: result.rowCount }); |
||||
} |
||||
|
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* Execute a query with automatic client release |
||||
* @param {string} text - SQL query text |
||||
* @param {Array} params - Query parameters |
||||
* @returns {Promise<pg.QueryResult>} Query result |
||||
*/ |
||||
export async function queryWithClient(text, params) { |
||||
const client = await pool.connect(); |
||||
try { |
||||
return await client.query(text, params); |
||||
} finally { |
||||
client.release(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Execute a transaction |
||||
* @param {Function} callback - Async function receiving client as parameter |
||||
* @returns {Promise<any>} Transaction result |
||||
*/ |
||||
export async function transaction(callback) { |
||||
const client = await pool.connect(); |
||||
try { |
||||
await client.query('BEGIN'); |
||||
const result = await callback(client); |
||||
await client.query('COMMIT'); |
||||
return result; |
||||
} catch (error) { |
||||
await client.query('ROLLBACK'); |
||||
throw error; |
||||
} finally { |
||||
client.release(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Get a client from the pool |
||||
* @returns {Promise<pg.PoolClient>} Pool client |
||||
*/ |
||||
export async function getClient() { |
||||
return pool.connect(); |
||||
} |
||||
|
||||
/** |
||||
* Get pool status information |
||||
* @returns {Object} Pool statistics |
||||
*/ |
||||
export function getPoolStatus() { |
||||
return { |
||||
totalCount: pool.totalCount, |
||||
idleCount: pool.idleCount, |
||||
waitingCount: pool.waitingCount, |
||||
}; |
||||
} |
||||
|
||||
/** |
||||
* Close the connection pool |
||||
* @returns {Promise<void>} |
||||
*/ |
||||
export async function closePool() { |
||||
await pool.end(); |
||||
} |
||||
|
||||
// Default export the pool for direct access if needed
|
||||
export default pool; |
||||
@ -0,0 +1,42 @@
|
||||
/** |
||||
* Параметры пула node-postgres, единообразно с HR_TG_Bot / Postgres_TG_Bots: |
||||
* приоритет у `DATABASE_URL` (postgresql://…), иначе DB_HOST, DB_PORT, DB_NAME, …
|
||||
*/ |
||||
|
||||
import dotenv from 'dotenv'; |
||||
|
||||
dotenv.config(); |
||||
|
||||
/** |
||||
* @param {import('pg').PoolConfig} [overrides] |
||||
* @returns {import('pg').PoolConfig} |
||||
*/ |
||||
export function getPoolConfig(overrides = {}) { |
||||
const url = process.env.DATABASE_URL?.trim(); |
||||
if (url) { |
||||
return { |
||||
connectionString: url, |
||||
max: parseInt(process.env.DB_POOL_MAX || '20', 10), |
||||
idleTimeoutMillis: parseInt(process.env.DB_IDLE_TIMEOUT || '30000', 10), |
||||
connectionTimeoutMillis: parseInt( |
||||
process.env.DB_CONNECTION_TIMEOUT || '2000', |
||||
10 |
||||
), |
||||
...overrides, |
||||
}; |
||||
} |
||||
return { |
||||
host: process.env.DB_HOST || 'localhost', |
||||
port: parseInt(process.env.DB_PORT || '5432', 10), |
||||
database: process.env.DB_NAME || 'clinic_tests', |
||||
user: process.env.DB_USER || 'developer', |
||||
password: process.env.DB_PASSWORD || 'dev_password', |
||||
max: parseInt(process.env.DB_POOL_MAX || '20', 10), |
||||
idleTimeoutMillis: parseInt(process.env.DB_IDLE_TIMEOUT || '30000', 10), |
||||
connectionTimeoutMillis: parseInt( |
||||
process.env.DB_CONNECTION_TIMEOUT || '2000', |
||||
10 |
||||
), |
||||
...overrides, |
||||
}; |
||||
} |
||||
@ -0,0 +1,19 @@
|
||||
# Опционально: изолированный Postgres на 5433, если не используете общий кластер из |
||||
# ../Postgres_TG_Bots/docker-compose.dev.yml (сеть hr_postgres_dev_net, порт 5432). |
||||
# Основной сценарий: поднять Postgres там, создать БД clinic_tests, в backend/.env задать DATABASE_URL |
||||
# (см. backend/.env.example) — аналогично HR_TG_Bot (DATABASE_URL к hr_postgres_dev или localhost:5432). |
||||
|
||||
services: |
||||
postgres: |
||||
image: postgres:15 |
||||
environment: |
||||
POSTGRES_DB: clinic_tests |
||||
POSTGRES_USER: developer |
||||
POSTGRES_PASSWORD: dev_password |
||||
ports: |
||||
- "5433:5432" |
||||
volumes: |
||||
- postgres_data:/var/lib/postgresql/data |
||||
|
||||
volumes: |
||||
postgres_data: |
||||
Loading…
Reference in new issue