From 439f5d10336e3233f8fd4aec369700a48c549651 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Tue, 8 Aug 2023 17:05:56 +0300 Subject: [PATCH] Delay missed backfill if messages are recent --- backfill.go | 32 ++++++++++++++++++++++++++++---- portal.go | 5 +++-- user.go | 2 +- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/backfill.go b/backfill.go index cebc8d7..86dff9a 100644 --- a/backfill.go +++ b/backfill.go @@ -43,17 +43,41 @@ func (portal *Portal) initialForwardBackfill(user *User, markRead bool) { portal.forwardBackfill(ctx, user, time.Time{}, portal.bridge.Config.Bridge.Backfill.InitialLimit, markRead) } +const recentBackfillDelay = 15 * time.Second + +type pendingBackfill struct { + cancel context.CancelFunc + lastMessageID string + lastMessageTS time.Time +} + func (portal *Portal) missedForwardBackfill(user *User, lastMessageTS time.Time, lastMessageID string, markRead bool) bool { if portal.bridge.Config.Bridge.Backfill.MissedLimit == 0 { return false } + log := portal.zlog.With(). + Str("action", "missed forward backfill"). + Str("latest_message_id", lastMessageID). + Logger() + ctx := log.WithContext(context.TODO()) + if time.Since(lastMessageTS) < 5*time.Minute { + var cancel context.CancelFunc + ctx, cancel = context.WithCancel(ctx) + prev := portal.pendingRecentBackfill.Swap(&pendingBackfill{cancel: cancel, lastMessageID: lastMessageID, lastMessageTS: lastMessageTS}) + if prev != nil { + prev.cancel() + } + log.Debug().Msg("Delaying missed forward backfill as latest message is new") + select { + case <-time.After(recentBackfillDelay): + case <-ctx.Done(): + log.Debug().Msg("Backfill was cancelled by a newer backfill") + return false + } + } portal.forwardBackfillLock.Lock() defer portal.forwardBackfillLock.Unlock() - log := portal.zlog.With(). - Str("action", "missed forward backfill"). - Logger() - ctx := log.WithContext(context.TODO()) if !lastMessageTS.IsZero() { if portal.lastMessageTS.IsZero() { lastMsg, err := portal.bridge.DB.Message.GetLastInChat(ctx, portal.Key) diff --git a/portal.go b/portal.go index 5e19249..9089daa 100644 --- a/portal.go +++ b/portal.go @@ -25,6 +25,7 @@ import ( _ "image/gif" "strings" "sync" + "sync/atomic" "time" "github.com/gabriel-vasile/mimetype" @@ -239,6 +240,8 @@ type Portal struct { forwardBackfillLock sync.Mutex lastMessageTS time.Time + pendingRecentBackfill atomic.Pointer[pendingBackfill] + recentlyHandled [recentlyHandledLength]string recentlyHandledLock sync.Mutex recentlyHandledIndex uint8 @@ -270,8 +273,6 @@ func (portal *Portal) handleMessageLoopItem(msg PortalMessage) { switch { case msg.evt != nil: portal.handleMessage(msg.source, msg.evt) - //case msg.receipt != nil: - // portal.handleReceipt(msg.receipt, msg.source) default: portal.zlog.Warn().Interface("portal_message", msg).Msg("Unexpected PortalMessage with no message") } diff --git a/user.go b/user.go index 8bb1a54..f461c12 100644 --- a/user.go +++ b/user.go @@ -831,8 +831,8 @@ func (user *User) syncConversation(v *gmproto.Conversation, source string) { } log.Debug().Msg("Syncing existing portal") portal.UpdateMetadata(user, v) - didBackfill := portal.missedForwardBackfill(user, time.UnixMicro(v.LastMessageTimestamp), v.LatestMessageID, !v.GetUnread()) user.syncChatDoublePuppetDetails(portal, v, false) + didBackfill := portal.missedForwardBackfill(user, time.UnixMicro(v.LastMessageTimestamp), v.LatestMessageID, !v.GetUnread()) if !didBackfill && !v.GetUnread() && v.LatestMessageID != "" && user.DoublePuppetIntent != nil { // TODO this would spam a lot of read receipts on startup //user.markSelfReadFull(portal, v.LatestMessageID)