Skip to content

Commit

Permalink
Add timeout for SendMessage calls
Browse files Browse the repository at this point in the history
  • Loading branch information
tulir committed Nov 14, 2023
1 parent 68b25b3 commit e8fa5b6
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 1 deletion.
4 changes: 3 additions & 1 deletion request.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,13 +139,15 @@ func (cli *Client) sendIQAsync(query infoQuery) (<-chan *waBinary.Node, error) {
return ch, err
}

const defaultRequestTimeout = 75 * time.Second

func (cli *Client) sendIQ(query infoQuery) (*waBinary.Node, error) {
resChan, data, err := cli.sendIQAsyncAndGetData(&query)
if err != nil {
return nil, err
}
if query.Timeout == 0 {
query.Timeout = 75 * time.Second
query.Timeout = defaultRequestTimeout
}
if query.Context == nil {
query.Context = context.Background()
Expand Down
18 changes: 18 additions & 0 deletions send.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ type SendRequestExtra struct {
ID types.MessageID
// Should the message be sent as a peer message (protocol messages to your own devices, e.g. app state key requests)
Peer bool
// A timeout for the send request. Unlike timeouts using the context parameter, this only applies
// to the actual response waiting and not preparing/encrypting the message.
// Defaults to 75 seconds. The timeout can be disabled by using a negative value.
Timeout time.Duration
}

// SendMessage sends the given message.
Expand Down Expand Up @@ -148,6 +152,9 @@ func (cli *Client) SendMessage(ctx context.Context, to types.JID, message *waPro
return
}

if req.Timeout == 0 {
req.Timeout = defaultRequestTimeout
}
if len(req.ID) == 0 {
req.ID = cli.GenerateMessageID()
}
Expand Down Expand Up @@ -202,9 +209,20 @@ func (cli *Client) SendMessage(ctx context.Context, to types.JID, message *waPro
return
}
var respNode *waBinary.Node
var timeoutChan <-chan time.Time
if req.Timeout > 0 {
timeoutChan = time.After(req.Timeout)
} else {
timeoutChan = make(<-chan time.Time)
}
select {
case respNode = <-respChan:
case <-timeoutChan:
cli.cancelResponse(req.ID, respChan)
err = ErrMessageTimedOut
return
case <-ctx.Done():
cli.cancelResponse(req.ID, respChan)
err = ctx.Err()
return
}
Expand Down

0 comments on commit e8fa5b6

Please sign in to comment.