()
| 69 | } |
| 70 | |
| 71 | async function main() { |
| 72 | const startTime = Date.now() |
| 73 | log('info', 'Discord bot script starting', { |
| 74 | pid: process.pid, |
| 75 | hostname: os.hostname(), |
| 76 | nodeVersion: process.version, |
| 77 | platform: process.platform, |
| 78 | }) |
| 79 | |
| 80 | // Handle SIGTERM/SIGINT - shutdown() handles deduplication internally |
| 81 | process.on('SIGTERM', () => { |
| 82 | log('info', 'Received SIGTERM signal') |
| 83 | void shutdown(0) |
| 84 | }) |
| 85 | process.on('SIGINT', () => { |
| 86 | log('info', 'Received SIGINT signal') |
| 87 | void shutdown(0) |
| 88 | }) |
| 89 | |
| 90 | let consecutiveErrors = 0 |
| 91 | let attemptCount = 0 |
| 92 | |
| 93 | while (!isShuttingDown) { |
| 94 | attemptCount++ |
| 95 | const elapsedSec = Math.round((Date.now() - startTime) / 1000) |
| 96 | log('info', `Attempting to acquire Discord bot lock`, { attemptCount, elapsedSeconds: elapsedSec }) |
| 97 | |
| 98 | let acquired = false |
| 99 | let handle: LockHandle | null = null |
| 100 | |
| 101 | try { |
| 102 | const result = await tryAcquireAdvisoryLock(ADVISORY_LOCK_IDS.DISCORD_BOT) |
| 103 | acquired = result.acquired |
| 104 | handle = result.handle |
| 105 | consecutiveErrors = 0 // Reset on successful DB connection |
| 106 | log('info', 'Lock acquisition attempt completed', { acquired, consecutiveErrors }) |
| 107 | } catch (error) { |
| 108 | consecutiveErrors++ |
| 109 | log('error', `Error acquiring lock`, { |
| 110 | consecutiveErrors, |
| 111 | maxErrors: MAX_CONSECUTIVE_ERRORS, |
| 112 | error: String(error), |
| 113 | }) |
| 114 | |
| 115 | if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) { |
| 116 | log('error', 'Too many consecutive errors, exiting...') |
| 117 | await shutdown(1) |
| 118 | return |
| 119 | } |
| 120 | |
| 121 | log('info', `Will retry in ${LOCK_RETRY_INTERVAL_MS / 1000} seconds...`) |
| 122 | await sleep(LOCK_RETRY_INTERVAL_MS) |
| 123 | continue |
| 124 | } |
| 125 | |
| 126 | if (!acquired || !handle) { |
| 127 | log('info', `Another instance is already running the Discord bot`, { |
| 128 | retryInSeconds: LOCK_RETRY_INTERVAL_MS / 1000, |
no test coverage detected