mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-07-13 15:14:49 -06:00
fix: improve createConversation method with caching and locking mechanisms
This commit is contained in:
parent
623efd86a2
commit
fc5965938e
@ -543,64 +543,64 @@ export class ChatwootService {
|
||||
}
|
||||
|
||||
public async createConversation(instance: InstanceDto, body: any) {
|
||||
const remoteJid = body.key.remoteJid;
|
||||
const cacheKey = `${instance.instanceName}:createConversation-${remoteJid}`;
|
||||
const lockKey = `${instance.instanceName}:lock:createConversation-${remoteJid}`;
|
||||
const maxWaitTime = 5000; // 5 secounds
|
||||
|
||||
try {
|
||||
this.logger.verbose('--- Start createConversation ---');
|
||||
this.logger.verbose(`--- Start createConversation ---`);
|
||||
this.logger.verbose(`Instance: ${JSON.stringify(instance)}`);
|
||||
|
||||
const client = await this.clientCw(instance);
|
||||
|
||||
if (!client) {
|
||||
this.logger.warn(`Client not found for instance: ${JSON.stringify(instance)}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const cacheKey = `${instance.instanceName}:createConversation-${body.key.remoteJid}`;
|
||||
this.logger.verbose(`Cache key: ${cacheKey}`);
|
||||
|
||||
// If it already exists in the cache, return conversationId
|
||||
if (await this.cache.has(cacheKey)) {
|
||||
this.logger.verbose(`Cache hit for key: ${cacheKey}`);
|
||||
const conversationId = (await this.cache.get(cacheKey)) as number;
|
||||
this.logger.verbose(`Cached conversation ID: ${conversationId}`);
|
||||
let conversationExists: conversation | boolean;
|
||||
try {
|
||||
conversationExists = await client.conversations.get({
|
||||
accountId: this.provider.accountId,
|
||||
conversationId: conversationId,
|
||||
});
|
||||
this.logger.verbose(`Conversation exists: ${JSON.stringify(conversationExists)}`);
|
||||
} catch (error) {
|
||||
this.logger.error(`Error getting conversation: ${error}`);
|
||||
conversationExists = false;
|
||||
}
|
||||
if (!conversationExists) {
|
||||
this.logger.verbose('Conversation does not exist, re-calling createConversation');
|
||||
this.cache.delete(cacheKey);
|
||||
return await this.createConversation(instance, body);
|
||||
}
|
||||
|
||||
const conversationId = await this.cache.get(cacheKey) as number;
|
||||
this.logger.verbose(`Found conversation to: ${remoteJid}, conversation ID: ${conversationId}`);
|
||||
return conversationId;
|
||||
}
|
||||
|
||||
const isGroup = body.key.remoteJid.includes('@g.us');
|
||||
this.logger.verbose(`Is group: ${isGroup}`);
|
||||
|
||||
const chatId = isGroup ? body.key.remoteJid : body.key.remoteJid.split('@')[0];
|
||||
this.logger.verbose(`Chat ID: ${chatId}`);
|
||||
|
||||
let nameContact: string;
|
||||
|
||||
nameContact = !body.key.fromMe ? body.pushName : chatId;
|
||||
this.logger.verbose(`Name contact: ${nameContact}`);
|
||||
|
||||
const filterInbox = await this.getInbox(instance);
|
||||
|
||||
if (!filterInbox) {
|
||||
this.logger.warn(`Inbox not found for instance: ${JSON.stringify(instance)}`);
|
||||
return null;
|
||||
// If lock already exists, wait until release or timeout
|
||||
if (await this.cache.has(lockKey)) {
|
||||
this.logger.verbose(`Operação de criação já em andamento para ${remoteJid}, aguardando resultado...`);
|
||||
const start = Date.now();
|
||||
while (await this.cache.has(lockKey)) {
|
||||
if (Date.now() - start > maxWaitTime) {
|
||||
this.logger.warn(`Timeout aguardando lock para ${remoteJid}`);
|
||||
break;
|
||||
}
|
||||
await new Promise(res => setTimeout(res, 300));
|
||||
if (await this.cache.has(cacheKey)) {
|
||||
const conversationId = await this.cache.get(cacheKey) as number;
|
||||
this.logger.verbose(`Resolves creation of: ${remoteJid}, conversation ID: ${conversationId}`);
|
||||
return conversationId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Adquire lock
|
||||
await this.cache.set(lockKey, true, 30);
|
||||
this.logger.verbose(`Bloqueio adquirido para: ${lockKey}`);
|
||||
|
||||
try {
|
||||
/*
|
||||
Double check after lock
|
||||
Utilizei uma nova verificação para evitar que outra thread execute entre o terminio do while e o set lock
|
||||
*/
|
||||
if (await this.cache.has(cacheKey)) {
|
||||
return await this.cache.get(cacheKey) as number;
|
||||
}
|
||||
|
||||
const client = await this.clientCw(instance);
|
||||
if (!client) return null;
|
||||
|
||||
const isGroup = remoteJid.includes('@g.us');
|
||||
const chatId = isGroup ? remoteJid : remoteJid.split('@')[0];
|
||||
let nameContact = !body.key.fromMe ? body.pushName : chatId;
|
||||
const filterInbox = await this.getInbox(instance);
|
||||
if (!filterInbox) return null;
|
||||
|
||||
if (isGroup) {
|
||||
this.logger.verbose('Processing group conversation');
|
||||
this.logger.verbose(`Processing group conversation`);
|
||||
const group = await this.waMonitor.waInstances[instance.instanceName].client.groupMetadata(chatId);
|
||||
this.logger.verbose(`Group metadata: ${JSON.stringify(group)}`);
|
||||
|
||||
@ -638,9 +638,9 @@ export class ChatwootService {
|
||||
this.logger.verbose(`Contact profile picture URL: ${JSON.stringify(picture_url)}`);
|
||||
|
||||
let contact = await this.findContact(instance, chatId);
|
||||
this.logger.verbose(`Found contact: ${JSON.stringify(contact)}`);
|
||||
|
||||
if (contact) {
|
||||
this.logger.verbose(`Found contact: ${JSON.stringify(contact)}`);
|
||||
if (!body.key.fromMe) {
|
||||
const waProfilePictureFile =
|
||||
picture_url?.profilePictureUrl?.split('#')[0].split('?')[0].split('/').pop() || '';
|
||||
@ -680,7 +680,7 @@ export class ChatwootService {
|
||||
}
|
||||
|
||||
if (!contact) {
|
||||
this.logger.warn('Contact not created or found');
|
||||
this.logger.warn(`Contact not created or found`);
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -694,7 +694,7 @@ export class ChatwootService {
|
||||
this.logger.verbose(`Contact conversations: ${JSON.stringify(contactConversations)}`);
|
||||
|
||||
if (!contactConversations || !contactConversations.payload) {
|
||||
this.logger.error('No conversations found or payload is undefined');
|
||||
this.logger.error(`No conversations found or payload is undefined`);
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -743,15 +743,20 @@ export class ChatwootService {
|
||||
});
|
||||
|
||||
if (!conversation) {
|
||||
this.logger.warn('Conversation not created or found');
|
||||
this.logger.warn(`Conversation not created or found`);
|
||||
return null;
|
||||
}
|
||||
|
||||
this.logger.verbose(`New conversation created with ID: ${conversation.id}`);
|
||||
this.cache.set(cacheKey, conversation.id);
|
||||
return conversation.id;
|
||||
} finally {
|
||||
await this.cache.delete(lockKey);
|
||||
this.logger.verbose(`Block released for: ${lockKey}`);
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.error(`Error in createConversation: ${error}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user