()
| 26 | } |
| 27 | |
| 28 | async _establishConnection() { |
| 29 | const retries = Number.isFinite(pgConfig.options.retries) ? pgConfig.options.retries : 0; |
| 30 | const baseDelay = Number.isFinite(pgConfig.options.backoffBase) ? pgConfig.options.backoffBase : 100; |
| 31 | const multiplier = Number.isFinite(pgConfig.options.backoffMultiplier) ? pgConfig.options.backoffMultiplier : 2; |
| 32 | const attempts = Math.max(1, retries + 1); |
| 33 | |
| 34 | for (let attempt = 1; attempt <= attempts; attempt += 1) { |
| 35 | try { |
| 36 | await new Promise(resolve => setTimeout(resolve, 100)); |
| 37 | |
| 38 | this.pool = new pg.Pool(resolvePostgresPoolConfig()); |
| 39 | |
| 40 | this.pool.on('error', (error, client) => { |
| 41 | logger.error('PostgreSQL pool error:', error); |
| 42 | }); |
| 43 | |
| 44 | const client = await this.pool.connect(); |
| 45 | await client.query('SELECT NOW()'); |
| 46 | client.release(); |
| 47 | |
| 48 | this.lastFailureReason = null; |
| 49 | this.lastFailureMessage = null; |
| 50 | |
| 51 | this.isConnected = true; |
| 52 | logger.info('PostgreSQL Database initialized successfully'); |
| 53 | |
| 54 | if (pgConfig.features.autoCreateTables) { |
| 55 | await this.createTables(); |
| 56 | |
| 57 | try { |
| 58 | const columnCheck = await this.pool.query(` |
| 59 | SELECT column_name |
| 60 | FROM information_schema.columns |
| 61 | WHERE table_name = 'guilds' AND column_name = 'counters' |
| 62 | `); |
| 63 | |
| 64 | if (columnCheck.rows.length === 0) { |
| 65 | await this.pool.query(` |
| 66 | ALTER TABLE ${pgConfig.tables.guilds} |
| 67 | ADD COLUMN counters JSONB DEFAULT '[]' |
| 68 | `); |
| 69 | logger.info('Added counters column to guilds table'); |
| 70 | } |
| 71 | } catch (error) { |
| 72 | logger.warn('Could not add counters column to guilds table:', error.message); |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | if (pgConfig.migration.enabled) { |
| 77 | const migrationCheck = await this.verifySchemaVersion(); |
| 78 | if (!migrationCheck.ok) { |
| 79 | const shouldBootstrapSchema = |
| 80 | migrationCheck.reason === 'MISSING_MIGRATION_VERSION' |
| 81 | && pgConfig.features.autoMigrate; |
| 82 | |
| 83 | if (shouldBootstrapSchema) { |
| 84 | await this.setSchemaVersion( |
| 85 | pgConfig.migration.expectedVersion, |
no test coverage detected