fix: stabilize WhatsApp connections and restore paired sessions on startup - #154
Open
member3541 wants to merge 3 commits into
Open
Conversation
…artup Prevent QR polling from restarting logged-in sessions, serialize instance lifecycle to avoid connection leaks, and reconnect paired instances after redeploy. Co-authored-by: Cursor <cursoragent@cursor.com>
Reviewer's GuideStabilizes WhatsApp instance lifecycle by serializing start/restart operations, introducing a controlled reconnect-with-backoff path that reuses sqlstore containers, preventing QR polling from restarting logged-in sessions, and restoring paired instances on startup based on persisted JIDs instead of transient connection state. Sequence diagram for QR polling without restarting logged-in sessionssequenceDiagram
actor User
participant InstanceHandler as instanceHandler
participant InstanceService as instanceService
participant WhatsmeowService as whatsmeowService
User->>InstanceHandler: Qr
InstanceHandler->>InstanceService: GetQr(instance)
InstanceService->>InstanceService: client = clientPointer[instance.Id]
alt client logged in
InstanceService->>InstanceHandler: return ErrSessionAlreadyLoggedIn
InstanceHandler->>User: HTTP 409 (connected=true)
else client nil or disconnected and not logged in
alt client is nil
InstanceService->>WhatsmeowService: StartInstance(instance.Id)
else client exists but disconnected
InstanceService->>WhatsmeowService: ReconnectClient(instance.Id)
end
WhatsmeowService-->>InstanceService: client ready for QR
InstanceService->>InstanceHandler: QrcodeStruct
InstanceHandler->>User: HTTP 200 QR code
end
File-Level Changes
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 found 2 issues, and left some high level feedback:
- The lifecycle coordination between
stopChannelanddoneis quite subtle; consider adding a small helper or comment block documenting the expected ordering (requestStop → closeDone → workerWG.Wait) to make it clearer how goroutines should shut down and avoid future races or deadlocks. - In
recoverConnection, the reconnect loop currently retries indefinitely whileStore.IDis set; it might be worth adding a hard cap or observability hook (metric/counter) so operators can detect or bound long-lived reconnect loops in the presence of persistent network issues.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The lifecycle coordination between `stopChannel` and `done` is quite subtle; consider adding a small helper or comment block documenting the expected ordering (requestStop → closeDone → workerWG.Wait) to make it clearer how goroutines should shut down and avoid future races or deadlocks.
- In `recoverConnection`, the reconnect loop currently retries indefinitely while `Store.ID` is set; it might be worth adding a hard cap or observability hook (metric/counter) so operators can detect or bound long-lived reconnect loops in the presence of persistent network issues.
## Individual Comments
### Comment 1
<location path="pkg/instance/service/instance_service.go" line_range="167-168" />
<code_context>
return client, nil
}
+func (i instances) signalStop(instanceID string) error {
+ stopChannel := i.killChannel[instanceID]
+ if stopChannel == nil {
+ return fmt.Errorf("instance stop channel not found")
</code_context>
<issue_to_address>
**issue (bug_risk):** signalStop relies on killChannel map that is no longer populated, breaking disconnect/logout paths
signalStop now uses i.killChannel, but newer flows (Connect, StartInstance, ClearInstanceCache, etc.) only manage stop channels in whatsmeowService (w.killChannel). As a result, Disconnect/Logout and other signalStop callers will frequently see "instance stop channel not found" for running instances. Please either route stop requests through whatsmeowService (e.g., a method using runtimePointers/killChannel there) or ensure i.killChannel is kept in sync with w.killChannel for all instance lifecycle operations.
</issue_to_address>
### Comment 2
<location path="pkg/instance/service/instance_service.go" line_range="719-725" />
<code_context>
+ if err := i.whatsmeowService.ReconnectClient(instanceId); err != nil {
</code_context>
<issue_to_address>
**issue (bug_risk):** ForceReconnect health check still uses local clientPointer, which may be stale after ReconnectClient
After calling whatsmeowService.ReconnectClient, the health check still uses i.clientPointer, but ReconnectClient manages state via whatsmeowService’s clientPointer/killChannel. If these differ from i.clientPointer, the check can falsely report a failed reconnect even when the new client is healthy. Consider either validating via whatsmeowService (e.g., runtimePointers) or making i.clientPointer the single, consistently updated source of truth in the same lifecycle path as whatsmeowService.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
Route stop/health checks through whatsmeow runtime pointers, document shutdown ordering, and cap automatic reconnect attempts with periodic warning logs. Co-authored-by: Cursor <cursoragent@cursor.com>
Author
|
Addressed review feedback:
|
Stop coordination now lives exclusively in whatsmeowService.RequestStop. Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Test plan
Summary by Sourcery
Stabilize WhatsApp instance lifecycle, introduce controlled reconnect behavior, and ensure paired sessions are restored cleanly on startup without disrupting authenticated clients.
New Features:
Bug Fixes:
Enhancements:
Build:
Chores: