Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions go/bind/notifications.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ import (
"fmt"
"regexp"
"runtime"
"strconv"
"sync"
"time"

lru "github.com/hashicorp/golang-lru"
"github.com/keybase/client/go/chat"
"github.com/keybase/client/go/chat/globals"
"github.com/keybase/client/go/chat/storage"
Expand All @@ -20,6 +23,21 @@ import (
"github.com/kyokomi/emoji"
)

const seenNotificationsCacheSize = 100

var (
seenNotificationsMtx sync.Mutex
seenNotifications *lru.Cache
seenNotificationsOnce sync.Once
)

func getSeenNotificationsCache() *lru.Cache {
seenNotificationsOnce.Do(func() {
seenNotifications, _ = lru.New(seenNotificationsCacheSize)
})
return seenNotifications
}

type Person struct {
KeybaseUsername string
KeybaseAvatar string
Expand Down Expand Up @@ -106,6 +124,20 @@ func HandleBackgroundNotification(strConvID, body, serverMessageBody, sender str
return libkb.LoginRequiredError{}
}
mp := chat.NewMobilePush(gc)
// Dedupe by convID||msgID
dupKey := strConvID + "||" + strconv.Itoa(intMessageID)
// Check if we've already processed this notification but without
// serializing the whole function. We check the map again while holding
// a lock before anything is displayed.
if _, ok := getSeenNotificationsCache().Get(dupKey); ok {
// Cancel any duplicate visible notifications
if len(pushID) > 0 {
mp.AckNotificationSuccess(ctx, []string{pushID})
}
kbCtx.Log.CDebugf(ctx, "HandleBackgroundNotification: duplicate notification convID=%s msgID=%d", strConvID, intMessageID)
// Return nil (not an error) so Android does not treat this as failure and show a fallback notification.
return nil
}
uid := gregor1.UID(kbCtx.Env.GetUID().ToBytes())
convID, err := chat1.MakeConvID(strConvID)
if err != nil {
Expand Down Expand Up @@ -195,7 +227,20 @@ func HandleBackgroundNotification(strConvID, body, serverMessageBody, sender str

// only display and ack this notification if we actually have something to display
if pusher != nil && (len(chatNotification.Message.Plaintext) > 0 || len(chatNotification.Message.ServerMessage) > 0) {
// Lock and check if we've already processed this notification.
seenNotificationsMtx.Lock()
defer seenNotificationsMtx.Unlock()
if _, ok := getSeenNotificationsCache().Get(dupKey); ok {
// Cancel any duplicate visible notifications
if len(pushID) > 0 {
mp.AckNotificationSuccess(ctx, []string{pushID})
}
kbCtx.Log.CDebugf(ctx, "HandleBackgroundNotification: duplicate notification convID=%s msgID=%d", strConvID, intMessageID)
// Return nil (not an error) so Android does not treat this as failure and show a fallback notification.
return nil
}
pusher.DisplayChatNotification(&chatNotification)
getSeenNotificationsCache().Add(dupKey, struct{}{})
if len(pushID) > 0 {
mp.AckNotificationSuccess(ctx, []string{pushID})
}
Expand Down