Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion BackEnd/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,13 @@ FF_ENABLE_NOTIFICATIONS_V2=false
# Database
DATABASE_URL=postgresql://user:password@localhost:5432/stellar_earn

# Query Logging Configuration
# Connection Pool
DB_POOL_MAX=10
DB_POOL_MIN=2
DB_POOL_CONNECTION_TIMEOUT=10000
DB_POOL_IDLE_TIMEOUT=30000

# Query Logging
DB_QUERY_LOGGING=true
SLOW_QUERY_THRESHOLD=1000
CRITICAL_QUERY_THRESHOLD=5000
Expand Down
13 changes: 5 additions & 8 deletions BackEnd/src/config/ormconfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,11 @@ export default new DataSource({
logging: process.env.NODE_ENV === 'development',
// Add these extra options for Neon
extra: {
ssl: {
rejectUnauthorized: false,
require: true,
},
// Connection pool settings
max: 10,
connectionTimeoutMillis: 10000,
idleTimeoutMillis: 30000,
ssl: { rejectUnauthorized: false, require: true },
max: parseInt(process.env.DB_POOL_MAX ?? '10', 10),
min: parseInt(process.env.DB_POOL_MIN ?? '2', 10),
connectionTimeoutMillis: parseInt(process.env.DB_POOL_CONNECTION_TIMEOUT ?? '10000', 10),
idleTimeoutMillis: parseInt(process.env.DB_POOL_IDLE_TIMEOUT ?? '30000', 10),
},
});

64 changes: 53 additions & 11 deletions BackEnd/src/database/data-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,30 @@ dotenv.config({ path: path.resolve(__dirname, '../../.env') });

class TypeORMQueryLogger implements Logger {
private readonly logger = new AppLoggerService();
private readonly slowQueryThreshold = parseInt(process.env.SLOW_QUERY_THRESHOLD || '1000'); // ms
private readonly enableQueryLogging = process.env.NODE_ENV === 'development' || process.env.DB_QUERY_LOGGING === 'true';
private readonly slowQueryThreshold = parseInt(
process.env.SLOW_QUERY_THRESHOLD || '1000',
10
);

private readonly enableQueryLogging =
process.env.NODE_ENV === 'development' ||
process.env.DB_QUERY_LOGGING === 'true';

logQuery(query: string, parameters?: any[]): void {
if (!this.enableQueryLogging) return;

this.logger.debug('Database Query', 'Database', {
query: query.trim(),
parameters,
type: 'query'
type: 'query',
});
}

logQueryError(error: string, query: string, parameters?: any[]): void {
this.logger.error('Database Query Error', error, 'Database', {
query: query.trim(),
parameters,
type: 'query_error'
type: 'query_error',
});
}

Expand All @@ -35,7 +41,7 @@ class TypeORMQueryLogger implements Logger {
parameters,
executionTime: time,
threshold: this.slowQueryThreshold,
type: 'slow_query'
type: 'slow_query',
});
}

Expand Down Expand Up @@ -65,15 +71,51 @@ class TypeORMQueryLogger implements Logger {
export const dataSourceOptions: DataSourceOptions = {
type: 'postgres',
url: process.env.DATABASE_URL,
entities: [path.join(__dirname, '..', '**', 'entities', '*.entity.{ts,js}')],
migrations: [path.join(__dirname, 'migrations', '*.{ts,js}')],

// Enable SSL only in production
ssl:
process.env.NODE_ENV === 'production'
? { rejectUnauthorized: false }
: false,

entities: [
path.join(__dirname, '..', '**', 'entities', '*.entity.{ts,js}'),
],

migrations: [
path.join(__dirname, 'migrations', '*.{ts,js}'),
],

migrationsTableName: 'typeorm_migrations',
synchronize: false,
logging: process.env.NODE_ENV === 'development' || process.env.DB_QUERY_LOGGING === 'true',

logging:
process.env.NODE_ENV === 'development' ||
process.env.DB_QUERY_LOGGING === 'true',

logger: new TypeORMQueryLogger(),
maxQueryExecutionTime: parseInt(process.env.SLOW_QUERY_THRESHOLD || '1000'),

maxQueryExecutionTime: parseInt(
process.env.SLOW_QUERY_THRESHOLD || '1000',
10
),

extra: {
max: parseInt(process.env.DB_POOL_MAX ?? '10', 10),
min: parseInt(process.env.DB_POOL_MIN ?? '2', 10),

connectionTimeoutMillis: parseInt(
process.env.DB_POOL_CONNECTION_TIMEOUT ?? '10000',
10
),

idleTimeoutMillis: parseInt(
process.env.DB_POOL_IDLE_TIMEOUT ?? '30000',
10
),
},
};

const AppDataSource = new DataSource(dataSourceOptions);

export default AppDataSource;
export default AppDataSource;
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@ export class DatabasePoolMonitorService implements OnModuleInit, OnModuleDestroy
const extra = options.extra || {};

return {
max: extra.max || 10,
min: extra.min || 0,
connectionTimeoutMillis: extra.connectionTimeoutMillis || 10000,
idleTimeoutMillis: extra.idleTimeoutMillis || 30000,
max: extra.max ?? parseInt(process.env.DB_POOL_MAX ?? '10', 10),
min: extra.min ?? parseInt(process.env.DB_POOL_MIN ?? '2', 10),
connectionTimeoutMillis: extra.connectionTimeoutMillis ?? parseInt(process.env.DB_POOL_CONNECTION_TIMEOUT ?? '10000', 10),
idleTimeoutMillis: extra.idleTimeoutMillis ?? parseInt(process.env.DB_POOL_IDLE_TIMEOUT ?? '30000', 10),
};
}

Expand Down