retry: add optional semaphore for retry receipts

Closes #1119
This commit is contained in:
Tulir Asokan
2026-04-21 11:30:05 +03:00
parent 415df3167a
commit a5594bffb8
4 changed files with 22 additions and 0 deletions
+12
View File
@@ -26,6 +26,7 @@ import (
"go.mau.fi/util/ptr"
"go.mau.fi/util/random"
"golang.org/x/net/proxy"
"golang.org/x/sync/semaphore"
"go.mau.fi/whatsmeow/appstate"
waBinary "go.mau.fi/whatsmeow/binary"
@@ -119,6 +120,7 @@ type Client struct {
messageRetries map[string]int
messageRetriesLock sync.Mutex
retrySema *semaphore.Weighted
incomingRetryRequestCounter map[incomingRetryKey]int
incomingRetryRequestCounterLock sync.Mutex
@@ -403,6 +405,16 @@ func (cli *Client) SetPreLoginHTTPClient(h *http.Client) {
cli.preLoginHTTP = h
}
// SetMaxParallelRetryReceiptHandling sets how many retry receipts can be handled in parallel.
// Defaults to unlimited. This should only be set before connecting, changing it afterwards can cause data races.
func (cli *Client) SetMaxParallelRetryReceiptHandling(n int64) {
if n <= 0 {
cli.retrySema = nil
} else {
cli.retrySema = semaphore.NewWeighted(n)
}
}
func (cli *Client) getSocketWaitChan() <-chan struct{} {
cli.socketLock.RLock()
ch := cli.socketWait
+1
View File
@@ -13,6 +13,7 @@ require (
go.mau.fi/util v0.9.8
golang.org/x/crypto v0.50.0
golang.org/x/net v0.53.0
golang.org/x/sync v0.20.0
google.golang.org/protobuf v1.36.11
)
+2
View File
@@ -46,6 +46,8 @@ golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJk
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80=
golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
+7
View File
@@ -187,6 +187,13 @@ func (cli *Client) tryHandleRetryReceipt(ctx context.Context, receipt *events.Re
cli.Log.Errorf("Retry receipt handler panicked: %v\n%s", err, debug.Stack())
}
}()
if cli.retrySema != nil {
err := cli.retrySema.Acquire(ctx, 1)
if err != nil {
return
}
defer cli.retrySema.Release(1)
}
err := cli.handleRetryReceipt(ctx, receipt, node)
if err != nil {
cli.Log.Errorf("Failed to handle retry receipt for %s/%s from %s: %v", receipt.Chat, receipt.MessageIDs[0], receipt.Sender, err)