Persist offline mqtt events in the queueDir and replay (#7037)

This commit is contained in:
Praveen raj Mani
2019-01-14 12:39:00 +05:30
committed by Harshavardhana
parent 8757c963ba
commit 6571641735
27 changed files with 1507 additions and 265 deletions
+62 -30
View File
@@ -19,24 +19,33 @@ import (
"github.com/eclipse/paho.mqtt.golang/packets"
)
//PacketAndToken is a struct that contains both a ControlPacket and a
//Token. This struct is passed via channels between the client interface
//code and the underlying code responsible for sending and receiving
//MQTT messages.
// PacketAndToken is a struct that contains both a ControlPacket and a
// Token. This struct is passed via channels between the client interface
// code and the underlying code responsible for sending and receiving
// MQTT messages.
type PacketAndToken struct {
p packets.ControlPacket
t Token
t tokenCompletor
}
//Token defines the interface for the tokens used to indicate when
//actions have completed.
// Token defines the interface for the tokens used to indicate when
// actions have completed.
type Token interface {
Wait() bool
WaitTimeout(time.Duration) bool
flowComplete()
Error() error
}
type TokenErrorSetter interface {
setError(error)
}
type tokenCompletor interface {
Token
TokenErrorSetter
flowComplete()
}
type baseToken struct {
m sync.RWMutex
complete chan struct{}
@@ -56,25 +65,34 @@ func (b *baseToken) Wait() bool {
return b.ready
}
// WaitTimeout takes a time in ms to wait for the flow associated with the
// WaitTimeout takes a time.Duration to wait for the flow associated with the
// Token to complete, returns true if it returned before the timeout or
// returns false if the timeout occurred. In the case of a timeout the Token
// does not have an error set in case the caller wishes to wait again
func (b *baseToken) WaitTimeout(d time.Duration) bool {
b.m.Lock()
defer b.m.Unlock()
if !b.ready {
timer := time.NewTimer(d)
select {
case <-b.complete:
b.ready = true
case <-time.After(d):
if !timer.Stop() {
<-timer.C
}
case <-timer.C:
}
}
return b.ready
}
func (b *baseToken) flowComplete() {
close(b.complete)
select {
case <-b.complete:
default:
close(b.complete)
}
}
func (b *baseToken) Error() error {
@@ -83,7 +101,12 @@ func (b *baseToken) Error() error {
return b.err
}
func newToken(tType byte) Token {
func (b *baseToken) setError(e error) {
b.err = e
b.flowComplete()
}
func newToken(tType byte) tokenCompletor {
switch tType {
case packets.Connect:
return &ConnectToken{baseToken: baseToken{complete: make(chan struct{})}}
@@ -99,59 +122,68 @@ func newToken(tType byte) Token {
return nil
}
//ConnectToken is an extension of Token containing the extra fields
//required to provide information about calls to Connect()
// ConnectToken is an extension of Token containing the extra fields
// required to provide information about calls to Connect()
type ConnectToken struct {
baseToken
returnCode byte
returnCode byte
sessionPresent bool
}
//ReturnCode returns the acknowlegement code in the connack sent
//in response to a Connect()
// ReturnCode returns the acknowlegement code in the connack sent
// in response to a Connect()
func (c *ConnectToken) ReturnCode() byte {
c.m.RLock()
defer c.m.RUnlock()
return c.returnCode
}
//PublishToken is an extension of Token containing the extra fields
//required to provide information about calls to Publish()
// SessionPresent returns a bool representing the value of the
// session present field in the connack sent in response to a Connect()
func (c *ConnectToken) SessionPresent() bool {
c.m.RLock()
defer c.m.RUnlock()
return c.sessionPresent
}
// PublishToken is an extension of Token containing the extra fields
// required to provide information about calls to Publish()
type PublishToken struct {
baseToken
messageID uint16
}
//MessageID returns the MQTT message ID that was assigned to the
//Publish packet when it was sent to the broker
// MessageID returns the MQTT message ID that was assigned to the
// Publish packet when it was sent to the broker
func (p *PublishToken) MessageID() uint16 {
return p.messageID
}
//SubscribeToken is an extension of Token containing the extra fields
//required to provide information about calls to Subscribe()
// SubscribeToken is an extension of Token containing the extra fields
// required to provide information about calls to Subscribe()
type SubscribeToken struct {
baseToken
subs []string
subResult map[string]byte
}
//Result returns a map of topics that were subscribed to along with
//the matching return code from the broker. This is either the Qos
//value of the subscription or an error code.
// Result returns a map of topics that were subscribed to along with
// the matching return code from the broker. This is either the Qos
// value of the subscription or an error code.
func (s *SubscribeToken) Result() map[string]byte {
s.m.RLock()
defer s.m.RUnlock()
return s.subResult
}
//UnsubscribeToken is an extension of Token containing the extra fields
//required to provide information about calls to Unsubscribe()
// UnsubscribeToken is an extension of Token containing the extra fields
// required to provide information about calls to Unsubscribe()
type UnsubscribeToken struct {
baseToken
}
//DisconnectToken is an extension of Token containing the extra fields
//required to provide information about calls to Disconnect()
// DisconnectToken is an extension of Token containing the extra fields
// required to provide information about calls to Disconnect()
type DisconnectToken struct {
baseToken
}