Fix deduplicating updates that flip back and forth
This commit is contained in:
parent
d410ba1e0c
commit
ecae11f6b2
3 changed files with 28 additions and 15 deletions
|
@ -41,6 +41,11 @@ const RefreshTachyonBuffer = 1 * time.Hour
|
|||
type Proxy func(*http.Request) (*url.URL, error)
|
||||
type EventHandler func(evt any)
|
||||
|
||||
type updateDedupItem struct {
|
||||
id string
|
||||
hash [32]byte
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
Logger zerolog.Logger
|
||||
evHandler EventHandler
|
||||
|
@ -51,7 +56,7 @@ type Client struct {
|
|||
skipCount int
|
||||
disconnecting bool
|
||||
|
||||
recentUpdates [8][32]byte
|
||||
recentUpdates [8]updateDedupItem
|
||||
recentUpdatesPtr int
|
||||
|
||||
conversationsFetchedOnce bool
|
||||
|
|
|
@ -77,19 +77,23 @@ func (c *Client) decryptInternalMessage(data *gmproto.IncomingRPCMessage) (*Inco
|
|||
return msg, nil
|
||||
}
|
||||
|
||||
func (c *Client) deduplicateHash(hash [32]byte) bool {
|
||||
func (c *Client) deduplicateHash(id string, hash [32]byte) bool {
|
||||
const recentUpdatesLen = len(c.recentUpdates)
|
||||
for i := c.recentUpdatesPtr + recentUpdatesLen - 1; i >= c.recentUpdatesPtr; i-- {
|
||||
if c.recentUpdates[i%recentUpdatesLen] == hash {
|
||||
if c.recentUpdates[i%recentUpdatesLen].id == id {
|
||||
if c.recentUpdates[i%recentUpdatesLen].hash == hash {
|
||||
return true
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
c.recentUpdates[c.recentUpdatesPtr] = hash
|
||||
}
|
||||
c.recentUpdates[c.recentUpdatesPtr] = updateDedupItem{id: id, hash: hash}
|
||||
c.recentUpdatesPtr = (c.recentUpdatesPtr + 1) % recentUpdatesLen
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *Client) logContent(res *IncomingRPCMessage) {
|
||||
func (c *Client) logContent(res *IncomingRPCMessage, thingID string, contentHash []byte) {
|
||||
if c.Logger.Trace().Enabled() && (res.DecryptedData != nil || res.DecryptedMessage != nil) {
|
||||
evt := c.Logger.Trace()
|
||||
if res.DecryptedMessage != nil {
|
||||
|
@ -97,6 +101,10 @@ func (c *Client) logContent(res *IncomingRPCMessage) {
|
|||
}
|
||||
if res.DecryptedData != nil {
|
||||
evt.Str("data", base64.StdEncoding.EncodeToString(res.DecryptedData))
|
||||
if contentHash != nil {
|
||||
evt.Str("thing_id", thingID)
|
||||
evt.Hex("data_hash", contentHash)
|
||||
}
|
||||
} else {
|
||||
evt.Str("data", "<null>")
|
||||
}
|
||||
|
@ -104,14 +112,14 @@ func (c *Client) logContent(res *IncomingRPCMessage) {
|
|||
}
|
||||
}
|
||||
|
||||
func (c *Client) deduplicateUpdate(msg *IncomingRPCMessage) bool {
|
||||
func (c *Client) deduplicateUpdate(id string, msg *IncomingRPCMessage) bool {
|
||||
if msg.DecryptedData != nil {
|
||||
contentHash := sha256.Sum256(msg.DecryptedData)
|
||||
if c.deduplicateHash(contentHash) {
|
||||
c.Logger.Trace().Hex("data_hash", contentHash[:]).Msg("Ignoring duplicate update")
|
||||
if c.deduplicateHash(id, contentHash) {
|
||||
c.Logger.Trace().Str("thing_id", id).Hex("data_hash", contentHash[:]).Msg("Ignoring duplicate update")
|
||||
return true
|
||||
}
|
||||
c.logContent(msg)
|
||||
c.logContent(msg, id, contentHash[:])
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -16,27 +16,27 @@ func (c *Client) handleUpdatesEvent(msg *IncomingRPCMessage) {
|
|||
|
||||
switch evt := data.Event.(type) {
|
||||
case *gmproto.UpdateEvents_UserAlertEvent:
|
||||
c.logContent(msg)
|
||||
c.logContent(msg, "", nil)
|
||||
c.handleUserAlertEvent(msg, evt.UserAlertEvent)
|
||||
|
||||
case *gmproto.UpdateEvents_SettingsEvent:
|
||||
c.logContent(msg)
|
||||
c.logContent(msg, "", nil)
|
||||
c.triggerEvent(evt.SettingsEvent)
|
||||
|
||||
case *gmproto.UpdateEvents_ConversationEvent:
|
||||
if c.deduplicateUpdate(msg) {
|
||||
if c.deduplicateUpdate(evt.ConversationEvent.GetData().GetConversationID(), msg) {
|
||||
return
|
||||
}
|
||||
c.triggerEvent(evt.ConversationEvent.GetData())
|
||||
|
||||
case *gmproto.UpdateEvents_MessageEvent:
|
||||
if c.deduplicateUpdate(msg) {
|
||||
if c.deduplicateUpdate(evt.MessageEvent.GetData().GetMessageID(), msg) {
|
||||
return
|
||||
}
|
||||
c.triggerEvent(evt.MessageEvent.GetData())
|
||||
|
||||
case *gmproto.UpdateEvents_TypingEvent:
|
||||
c.logContent(msg)
|
||||
c.logContent(msg, "", nil)
|
||||
c.triggerEvent(evt.TypingEvent.GetData())
|
||||
|
||||
default:
|
||||
|
|
Loading…
Reference in a new issue