first commit

This commit is contained in:
Первов Артем
2026-06-19 08:18:52 +03:00
commit 05a9e0e535
61 changed files with 11950 additions and 0 deletions

65
src/db/db.service.ts Normal file
View File

@@ -0,0 +1,65 @@
import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { Pool, QueryResult, QueryResultRow } from 'pg';
import { getIntegerConfig } from '../common/config-number';
type DatabaseHealth = {
now: Date;
timescaledb_installed: boolean;
timescaledb_version: string | null;
};
@Injectable()
export class DbService implements OnModuleInit, OnModuleDestroy {
private pool!: Pool;
constructor(private readonly config: ConfigService) {}
/** Создает пул PostgreSQL и проверяет БД до начала обработки запросов. */
async onModuleInit(): Promise<void> {
const connectionString = this.config.get<string>('DATABASE_URL');
if (!connectionString) {
throw new Error('DATABASE_URL is required.');
}
this.pool = new Pool({
connectionString,
max: getIntegerConfig(this.config, 'PG_POOL_MAX', 20),
idleTimeoutMillis: 30_000,
connectionTimeoutMillis: 5_000,
statement_timeout: 60_000,
query_timeout: 60_000,
application_name: 'drill-cloud-v3',
});
await this.health();
}
/** Закрывает пул PostgreSQL при остановке Nest-приложения. */
async onModuleDestroy(): Promise<void> {
await this.pool?.end();
}
/** Выполняет параметризованный SQL-запрос через общий пул PostgreSQL. */
query<T extends QueryResultRow = QueryResultRow>(
text: string,
values: readonly unknown[] = [],
): Promise<QueryResult<T>> {
return this.pool.query<T>(text, [...values]);
}
/** Возвращает легкий health-снимок БД, включая статус расширения TimescaleDB. */
async health(): Promise<DatabaseHealth> {
const result = await this.query<DatabaseHealth>(`
SELECT
now(),
ext.extversion IS NOT NULL AS timescaledb_installed,
ext.extversion AS timescaledb_version
FROM (SELECT 1) AS probe
LEFT JOIN pg_extension AS ext
ON ext.extname = 'timescaledb'
`);
return result.rows[0];
}
}