Fix deduplicating updates that flip back and forth

This commit is contained in:
Tulir Asokan 2023-07-19 22:29:30 +03:00
parent d410ba1e0c
commit ecae11f6b2
3 changed files with 28 additions and 15 deletions

View file

@ -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

View file

@ -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
}

View file

@ -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: