Skip to content

Commit

Permalink
Merge pull request #659 from ChIoT-Tech/master
Browse files Browse the repository at this point in the history
Clarify use of token.WaitTimeout
  • Loading branch information
MattBrittan committed Nov 7, 2023
2 parents c26bc8b + e855a0b commit 5786441
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 1 deletion.
7 changes: 6 additions & 1 deletion client_test.go
Expand Up @@ -63,7 +63,12 @@ func TestCustomConnectionFunction(t *testing.T) {
client := NewClient(options)

// Try to connect using custom function, wait for 2 seconds, to pass MQTT first message
if token := client.Connect(); token.WaitTimeout(2*time.Second) && token.Error() != nil {
// Note that the token should NOT complete (because a CONNACK is never sent)
token := client.Connect()
if token.WaitTimeout(2 * time.Second) {
t.Fatal("token should not complete") // should be blocked waiting for CONNACK
}
if token.Error() != nil { // Should never have an error
t.Fatalf("%v", token.Error())
}

Expand Down
18 changes: 18 additions & 0 deletions token.go
Expand Up @@ -17,6 +17,7 @@
package mqtt

import (
"errors"
"sync"
"time"

Expand Down Expand Up @@ -202,3 +203,20 @@ type UnsubscribeToken struct {
type DisconnectToken struct {
baseToken
}

// TimedOut is the error returned by WaitTimeout when the timeout expires
var TimedOut = errors.New("context canceled")

// WaitTokenTimeout is a utility function used to simplify the use of token.WaitTimeout
// token.WaitTimeout may return `false` due to time out but t.Error() still results
// in nil.
// `if t := client.X(); t.WaitTimeout(time.Second) && t.Error() != nil {` may evaluate
// to false even if the operation fails.
// It is important to note that if TimedOut is returned, then the operation may still be running
// and could eventually complete successfully.
func WaitTokenTimeout(t Token, d time.Duration) error {
if !t.WaitTimeout(d) {
return TimedOut
}
return t.Error()
}
18 changes: 18 additions & 0 deletions token_test.go
Expand Up @@ -40,3 +40,21 @@ func TestWaitTimeout(t *testing.T) {
t.Fatal("Should have succeeded")
}
}

func TestWaitTokenTimeout(t *testing.T) {
b := baseToken{}

if !errors.Is(WaitTokenTimeout(&b, time.Second), TimedOut) {
t.Fatal("Should have failed")
}

// Now let's confirm that WaitTimeout returns correct error
b = baseToken{complete: make(chan struct{})}
testError := errors.New("test")
go func(bt *baseToken) {
bt.setError(testError)
}(&b)
if !errors.Is(WaitTokenTimeout(&b, 5*time.Second), testError) {
t.Fatal("Unexpected error received")
}
}

0 comments on commit 5786441

Please sign in to comment.