Files
api_builder/backend/src/services/DatabasePoolManager.ts
GEgorov c85fa20634 modified: backend/src/services/DatabasePoolManager.ts
modified:   backend/src/services/ScriptExecutor.ts
	modified:   backend/src/types/index.ts
	modified:   frontend/src/components/CodeEditor.tsx
	modified:   frontend/src/components/EndpointModal.tsx
	deleted:    frontend/src/pages/Databases.tsx
	modified:   frontend/src/pages/Settings.tsx
	modified:   frontend/src/types/index.ts
2025-10-07 20:16:53 +03:00

181 lines
5.0 KiB
TypeScript

import { Pool } from 'pg';
import { DatabaseConfig } from '../types';
import { mainPool } from '../config/database';
class DatabasePoolManager {
private pools: Map<string, Pool> = new Map();
async initialize() {
// Load databases from DB instead of env
await this.loadDatabasesFromDB();
}
private async loadDatabasesFromDB() {
try {
const result = await mainPool.query(
'SELECT * FROM databases WHERE is_active = true'
);
for (const row of result.rows) {
const dbConfig: DatabaseConfig = {
id: row.id,
name: row.name,
type: row.type,
host: row.host,
port: row.port,
database_name: row.database_name,
username: row.username,
password: row.password,
ssl: row.ssl,
is_active: row.is_active,
};
this.addPool(dbConfig);
}
console.log(`✅ Loaded ${result.rows.length} database connection(s) from DB`);
} catch (error) {
console.error('❌ Failed to load databases from DB:', error);
}
}
addPool(dbConfig: DatabaseConfig) {
if (this.pools.has(dbConfig.id)) {
console.warn(`Pool with id ${dbConfig.id} already exists. Skipping.`);
return;
}
const pool = new Pool({
host: dbConfig.host,
port: dbConfig.port,
database: dbConfig.database_name,
user: dbConfig.username,
password: dbConfig.password,
ssl: dbConfig.ssl ? { rejectUnauthorized: false } : false,
max: 20, // Увеличено количество соединений
idleTimeoutMillis: 60000, // 60 секунд
connectionTimeoutMillis: 10000, // 10 секунд (было 2 секунды)
keepAlive: true, // Поддерживать соединения активными
keepAliveInitialDelayMillis: 10000, // Начать keepAlive через 10 секунд
});
pool.on('error', (err) => {
console.error(`Database pool error for ${dbConfig.id}:`, err);
});
this.pools.set(dbConfig.id, pool);
console.log(`✅ Pool created for database: ${dbConfig.name} (${dbConfig.id})`);
}
removePool(databaseId: string) {
const pool = this.pools.get(databaseId);
if (pool) {
pool.end();
this.pools.delete(databaseId);
console.log(`Pool removed for database: ${databaseId}`);
}
}
getPool(databaseId: string): Pool | undefined {
return this.pools.get(databaseId);
}
async getDatabaseConfig(databaseId: string): Promise<DatabaseConfig | null> {
try {
const result = await mainPool.query(
'SELECT * FROM databases WHERE id = $1',
[databaseId]
);
if (result.rows.length === 0) {
return null;
}
const row = result.rows[0];
return {
id: row.id,
name: row.name,
type: row.type,
host: row.host,
port: row.port,
database_name: row.database_name,
username: row.username,
password: row.password,
ssl: row.ssl,
is_active: row.is_active,
aql_base_url: row.aql_base_url,
aql_auth_type: row.aql_auth_type,
aql_auth_value: row.aql_auth_value,
aql_headers: row.aql_headers,
};
} catch (error) {
console.error('Error fetching database config:', error);
return null;
}
}
async getAllDatabaseConfigs(): Promise<DatabaseConfig[]> {
try {
const result = await mainPool.query(
'SELECT id, name, type, host, port, database_name, is_active FROM databases WHERE is_active = true'
);
return result.rows;
} catch (error) {
console.error('Error fetching databases:', error);
return [];
}
}
async testConnection(databaseId: string): Promise<boolean> {
const pool = this.getPool(databaseId);
if (!pool) {
return false;
}
try {
const client = await pool.connect();
client.release();
return true;
} catch (error) {
console.error(`Connection test failed for ${databaseId}:`, error);
return false;
}
}
async reloadPool(databaseId: string) {
// Remove old pool
this.removePool(databaseId);
// Load new config from DB
const result = await mainPool.query(
'SELECT * FROM databases WHERE id = $1 AND is_active = true',
[databaseId]
);
if (result.rows.length > 0) {
const row = result.rows[0];
const dbConfig: DatabaseConfig = {
id: row.id,
name: row.name,
type: row.type,
host: row.host,
port: row.port,
database_name: row.database_name,
username: row.username,
password: row.password,
ssl: row.ssl,
is_active: row.is_active,
};
this.addPool(dbConfig);
}
}
async closeAll() {
const promises = Array.from(this.pools.values()).map((pool) => pool.end());
await Promise.all(promises);
this.pools.clear();
console.log('All database pools closed');
}
}
export const databasePoolManager = new DatabasePoolManager();