fix(evolution): prevent Evolution instances from getting stuck in 'cl…#2420
Conversation
…ose' state Evolution is a webhook-based integration that should always be considered 'open' since it passively receives events. Three changes fix the issue: 1. monitor.service.ts: Always call connectToWhatsapp() for Evolution instances on server restart, regardless of stored connection status. 2. instance.controller.ts: Call connectToWhatsapp() for Evolution instances during creation to initialize Chatwoot settings. 3. evolution.channel.service.ts: Restore stateConnection to 'open' and persist it to DB when connectToWhatsapp() is called in init mode. Closes EvolutionAPI#2419 https://claude.ai/code/session_013wxk4cj5U2H5fr2cxCgWdH
Reviewer's guide (collapsed on small PRs)Reviewer's GuideEnsures Evolution WhatsApp integration instances are always treated as 'open' webhook-based connections by auto-connecting them on startup/creation and resetting their connection state to 'open' when initialized, including persisting that state to the database. Sequence diagram for Evolution instance auto-connect on server restartsequenceDiagram
participant Server
participant WAMonitoringService
participant PrismaRepository
participant EvolutionStartupService
Server->>WAMonitoringService: onStartup()
WAMonitoringService->>PrismaRepository: findManyInstances()
PrismaRepository-->>WAMonitoringService: instanceList
loop forEach instanceData
WAMonitoringService->>WAMonitoringService: shouldAutoConnect(instanceData)
alt instanceData.connectionStatus is open or connecting or integration is EVOLUTION
WAMonitoringService->>EvolutionStartupService: connectToWhatsapp(instanceData)
alt data is not provided (init mode)
EvolutionStartupService->>EvolutionStartupService: stateConnection = { state: open }
alt instanceId is defined
EvolutionStartupService->>PrismaRepository: updateInstance(id, connectionStatus = open)
PrismaRepository-->>EvolutionStartupService: updatedInstance
end
EvolutionStartupService->>EvolutionStartupService: loadChatwoot()
else data is provided
EvolutionStartupService->>EvolutionStartupService: normal connection flow
end
else no auto connect
WAMonitoringService->>WAMonitoringService: skipConnect(instanceData)
end
end
Sequence diagram for Evolution instance creation and initializationsequenceDiagram
actor Client
participant InstanceController
participant PrismaRepository
participant EvolutionStartupService
Client->>InstanceController: createInstance(requestBody)
InstanceController->>PrismaRepository: createInstanceInDatabase(requestBody)
PrismaRepository-->>InstanceController: instanceData
InstanceController->>EvolutionStartupService: createInstance(instanceData)
EvolutionStartupService-->>InstanceController: instance
InstanceController->>InstanceController: prepareResponseData(instance, instanceData)
alt instanceData.integration is EVOLUTION
InstanceController->>EvolutionStartupService: connectToWhatsapp()
EvolutionStartupService->>EvolutionStartupService: stateConnection = { state: open }
alt instanceId is defined
EvolutionStartupService->>PrismaRepository: updateInstance(id, connectionStatus = open)
PrismaRepository-->>EvolutionStartupService: updatedInstance
end
EvolutionStartupService->>EvolutionStartupService: loadChatwoot()
end
InstanceController-->>Client: createdInstanceResponse
Updated class diagram for Evolution startup, monitoring, and instance controllerclassDiagram
class WAMonitoringService {
- logger
- prismaRepository
+ onStartup() void
+ monitorInstances() void
+ connectInstance(instanceData) void
}
class InstanceController {
- prismaRepository
- logger
+ createInstance(requestBody) Promise
+ getInstance(instanceId) Promise
}
class EvolutionStartupService {
- prismaRepository
- instanceId
- stateConnection
+ connectToWhatsapp(data) Promise
+ loadChatwoot() void
}
class PrismaRepository {
+ findManyInstances() Promise
+ updateInstance(id, connectionStatus) Promise
+ createInstanceInDatabase(requestBody) Promise
}
class Integration {
<<enumeration>>
EVOLUTION
OTHER
}
WAMonitoringService --> PrismaRepository : uses
WAMonitoringService --> EvolutionStartupService : creates_and_connects
InstanceController --> PrismaRepository : uses
InstanceController --> EvolutionStartupService : initializes_and_connects
EvolutionStartupService --> PrismaRepository : updates_instance_state
InstanceController --> Integration : checks_integration_type
WAMonitoringService --> Integration : checks_integration_type
File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- In
InstanceController, consider whetherawait instance.connectToWhatsapp()on Evolution creation should block the whole request (and potentially fail instance creation on connection/init errors) or if it would be safer to kick this off asynchronously and surface errors via monitoring instead. - The auto-connect log message in
WAMonitoringServicestill reportsconnectionStatuseven when auto-connecting solely becauseintegration === Integration.EVOLUTION; consider clarifying the log text or including the integration type so the reason for auto-connection is unambiguous in logs.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In `InstanceController`, consider whether `await instance.connectToWhatsapp()` on Evolution creation should block the whole request (and potentially fail instance creation on connection/init errors) or if it would be safer to kick this off asynchronously and surface errors via monitoring instead.
- The auto-connect log message in `WAMonitoringService` still reports `connectionStatus` even when auto-connecting solely because `integration === Integration.EVOLUTION`; consider clarifying the log text or including the integration type so the reason for auto-connection is unambiguous in logs.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
Integrates 3 key stability improvements: • PR evolution-foundation#2420: Prevent Evolution instances from getting stuck in 'close' state - Auto-connect Evolution instances on startup - Force 'open' state for webhook-based integrations - Update monitor service to handle Evolution integration • PR evolution-foundation#2372: Enhance contact and chat handling with improved JID mapping - Fix remoteLid vs remoteJid mapping in messaging-history.set - Add debug logs for better troubleshooting - Prevent orphaned chats without proper contact association - Clean remoteLid before database storage • PR evolution-foundation#2427: Improve audio upsert reliability and GHCR workflow - Prevent early returns that skip message upsert emission - Add guarded fallback for inbound audio messages - Add GitHub Actions workflow for GHCR image publishing These improvements enhance: - Connection stability for Evolution instances - Contact/chat mapping accuracy - Audio message reliability - CI/CD with GHCR support All changes are non-breaking and backward compatible.
…olution-foundation#2420) Forces Evolution integration instances to 'open' status on connect and ensures auto-reconnect on startup regardless of stored connection status. Upstream PR: evolution-foundation#2420 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Hi! As part of our PR triage, we noticed the Check Code Quality workflow has not run on this PR (it requires maintainer approval for first-time external contributors, which we've now enabled). To trigger CI:
Once CI runs and is green I'll re-review for merge. Thanks! |
DavidsonGomes
left a comment
There was a problem hiding this comment.
LGTM. Fix cirúrgico (18 linhas em 3 arquivos) que endereça um bug real: instâncias EVOLUTION (webhook-only) ficando presas em 'close' após boot. A lógica é coerente — auto-connect no monitor + connect on create + persistir open no DB.
Nota para validação manual: confirmar em reinício com várias instâncias EVOLUTION + Chatwoot que loadChatwoot() é idempotente quando chamado N vezes (não cria duplicatas de conversation/inbox).
…ose' state
Evolution is a webhook-based integration that should always be considered 'open' since it passively receives events. Three changes fix the issue:
Closes #2419
https://claude.ai/code/session_013wxk4cj5U2H5fr2cxCgWdH
📋 Description
🔗 Related Issue
Closes #(issue_number)
🧪 Type of Change
🧪 Testing
📸 Screenshots (if applicable)
✅ Checklist
📝 Additional Notes
Summary by Sourcery
Ensure Evolution WhatsApp integrations are always initialized and marked as open so they do not remain stuck in a closed state.
Bug Fixes: