refactor: implement exponential backoff patterns and extract magic numbers to constants

- Extract HTTP timeout constant (60s for large file downloads)
- Extract S3/MinIO retry configuration (3 retries, 1s-8s exponential backoff)
- Extract database polling retry configuration (5 retries, 100ms-2s exponential backoff)
- Extract webhook and lock polling delays to named constants
- Extract cache TTL values (5min for messages, 30min for updates) in Baileys service
- Implement exponential backoff for S3/MinIO downloads following webhook controller pattern
- Implement exponential backoff for database polling removing fixed delays
- Add deletion event lock to prevent race conditions with duplicate webhooks
- Process deletion events immediately (no delay) to fix Chatwoot local storage red error
- Make i18n translations path configurable via TRANSLATIONS_BASE_DIR env variable
- Add detailed logging for deletion events debugging

Addresses code review suggestions from Sourcery AI and Copilot AI:
- Magic numbers extracted to well-documented constants
- Retry configurations consolidated and clearly separated by use case
- S3/MinIO retry uses longer delays (external storage)
- Database polling uses shorter delays (internal operations)
- Fixes Chatwoot local storage deletion error (red message issue)
- Maintains full compatibility with S3/MinIO storage (tested)

Breaking changes: None - all changes are internal improvements
This commit is contained in:
Anderson Silva
2025-10-06 15:10:38 -03:00
parent 6e1d027750
commit e13434804c
3 changed files with 111 additions and 35 deletions

View File

@@ -254,6 +254,10 @@ export class BaileysStartupService extends ChannelStartupService {
private endSession = false;
private logBaileys = this.configService.get<Log>('LOG').BAILEYS;
// Cache TTL constants (in seconds)
private readonly MESSAGE_CACHE_TTL_SECONDS = 5 * 60; // 5 minutes - avoid duplicate message processing
private readonly UPDATE_CACHE_TTL_SECONDS = 30 * 60; // 30 minutes - avoid duplicate status updates
public stateConnection: wa.StateConnection = { state: 'close' };
public phoneNumber: string;
@@ -1155,7 +1159,7 @@ export class BaileysStartupService extends ChannelStartupService {
continue;
}
await this.baileysCache.set(messageKey, true, 5 * 60);
await this.baileysCache.set(messageKey, true, this.MESSAGE_CACHE_TTL_SECONDS);
if (
(type !== 'notify' && type !== 'append') ||
@@ -1275,7 +1279,7 @@ export class BaileysStartupService extends ChannelStartupService {
await this.updateMessagesReadedByTimestamp(remoteJid, timestamp);
}
await this.baileysCache.set(messageKey, true, 5 * 60);
await this.baileysCache.set(messageKey, true, this.MESSAGE_CACHE_TTL_SECONDS);
} else {
this.logger.info(`Update readed messages duplicated ignored [avoid deadlock]: ${messageKey}`);
}
@@ -1459,7 +1463,7 @@ export class BaileysStartupService extends ChannelStartupService {
}
if (!isDeletedMessage) {
await this.baileysCache.set(updateKey, true, 30 * 60);
await this.baileysCache.set(updateKey, true, this.UPDATE_CACHE_TTL_SECONDS);
}
if (status[update.status] === 'READ' && key.fromMe) {
@@ -1543,7 +1547,7 @@ export class BaileysStartupService extends ChannelStartupService {
if (status[update.status] === status[4]) {
this.logger.log(`Update as read in message.update ${remoteJid} - ${timestamp}`);
await this.updateMessagesReadedByTimestamp(remoteJid, timestamp);
await this.baileysCache.set(messageKey, true, 5 * 60);
await this.baileysCache.set(messageKey, true, this.MESSAGE_CACHE_TTL_SECONDS);
}
await this.prismaRepository.message.update({