From 5e1f867b2d3ccb5b7154075e503f41239e77565f Mon Sep 17 00:00:00 2001 From: iamxvbaba <28732408+iamxvbaba@users.noreply.github.com> Date: Wed, 29 Jul 2026 16:19:04 +0800 Subject: [PATCH] fix(channels): sync stop replaying clear-history updates --- internal/app/channels/service.go | 8 ----- internal/domain/channel.go | 18 ++++------ internal/rpc/channels_messages_rpc_test.go | 39 ++++++++-------------- internal/rpc/convert_updates.go | 8 +---- 4 files changed, 22 insertions(+), 51 deletions(-) diff --git a/internal/app/channels/service.go b/internal/app/channels/service.go index 6d527ff6..c3545bf5 100644 --- a/internal/app/channels/service.go +++ b/internal/app/channels/service.go @@ -2302,14 +2302,6 @@ func (s *Service) GetDifference(ctx context.Context, userID int64, req domain.Ch return domain.ChannelDifference{}, err } diff = s.filterBotChannelDifference(ctx, userID, diff) - if diff.Self.HistoryClearAnchorID > 0 && - diff.Self.HistoryClearAnchorID == diff.Self.AvailableMinID && - !diff.TooLong { - // updateChannelAvailableMessages is an absolute no-PTS update. Keep it - // outside ChannelUpdateEvent so channel difference continuity remains - // defined solely by real channel events. - diff.AvailableMinID = diff.Self.AvailableMinID - } return diff, nil } diff --git a/internal/domain/channel.go b/internal/domain/channel.go index 36734100..92d7f1f3 100644 --- a/internal/domain/channel.go +++ b/internal/domain/channel.go @@ -1335,17 +1335,13 @@ type ChannelDifference struct { Events []ChannelUpdateEvent NewMessages []ChannelMessage OtherUpdates []ChannelUpdateEvent - // AvailableMinID is an owner-local, absolute no-PTS boundary appended to a - // normal channel difference. It must never be represented as a synthetic - // ChannelUpdateEvent because updateChannelAvailableMessages has no pts. - AvailableMinID int - Users []User - Channels []Channel - Pts int - Final bool - TooLong bool - Dialog ChannelDialog - Timeout int + Users []User + Channels []Channel + Pts int + Final bool + TooLong bool + Dialog ChannelDialog + Timeout int } // DirtyChannel identifies an active channel with shared channel updates and/or diff --git a/internal/rpc/channels_messages_rpc_test.go b/internal/rpc/channels_messages_rpc_test.go index f36adbb6..22b0894d 100644 --- a/internal/rpc/channels_messages_rpc_test.go +++ b/internal/rpc/channels_messages_rpc_test.go @@ -273,32 +273,21 @@ func TestChannelsDeleteHistoryLocalClearEmitsAvailableMessagesUpdate(t *testing. t.Fatalf("offline account state = %+v, want unchanged pts=%d and non-regressing date", offlineDiff.State, stateBefore.Pts) } - channelOffline, err := r.onUpdatesGetChannelDifference(WithUserID(ctx, owner.ID), &tg.UpdatesGetChannelDifferenceRequest{ - Channel: &tg.InputChannel{ChannelID: channel.ID, AccessHash: channel.AccessHash}, - Filter: &tg.ChannelMessagesFilterEmpty{}, - Pts: newChannelUpdate.Pts, - Limit: 100, - }) - if err != nil { - t.Fatalf("channel difference after offline local clear: %v", err) - } - channelDiff, ok := channelOffline.(*tg.UpdatesChannelDifference) - if !ok { - t.Fatalf("offline channel difference = %T %+v, want non-empty difference with absolute update", channelOffline, channelOffline) - } - var channelAvailable *tg.UpdateChannelAvailableMessages - for _, update := range channelDiff.OtherUpdates { - if value, ok := update.(*tg.UpdateChannelAvailableMessages); ok { - channelAvailable = value - break + for attempt := 1; attempt <= 2; attempt++ { + channelOffline, err := r.onUpdatesGetChannelDifference(WithUserID(ctx, owner.ID), &tg.UpdatesGetChannelDifferenceRequest{ + Channel: &tg.InputChannel{ChannelID: channel.ID, AccessHash: channel.AccessHash}, + Filter: &tg.ChannelMessagesFilterEmpty{}, + Pts: newChannelUpdate.Pts, + Limit: 100, + }) + if err != nil { + t.Fatalf("channel difference attempt %d after offline local clear: %v", attempt, err) + } + channelDiff, ok := channelOffline.(*tg.UpdatesChannelDifferenceEmpty) + if !ok || channelDiff.Pts != newChannelUpdate.Pts { + t.Fatalf("channel difference attempt %d = %T %+v, want empty with unchanged channel pts=%d", + attempt, channelOffline, channelOffline, newChannelUpdate.Pts) } - } - if channelAvailable == nil || - channelAvailable.ChannelID != channel.ID || - channelAvailable.AvailableMinID != msg.ID || - channelDiff.Pts != newChannelUpdate.Pts { - t.Fatalf("offline channel updates = %+v pts=%d, want available boundary %d with unchanged channel pts=%d", - channelDiff.OtherUpdates, channelDiff.Pts, msg.ID, newChannelUpdate.Pts) } req := &tg.MessagesGetDialogsRequest{OffsetPeer: &tg.InputPeerEmpty{}, Limit: 20} diff --git a/internal/rpc/convert_updates.go b/internal/rpc/convert_updates.go index a12a48e7..fb1915e4 100644 --- a/internal/rpc/convert_updates.go +++ b/internal/rpc/convert_updates.go @@ -122,7 +122,7 @@ func tgChannelDifference(viewerUserID int64, diff domain.ChannelDifference) tg.U Users: tgUsersForViewer(viewerUserID, diff.Users), } } - if len(diff.Events) == 0 && len(diff.NewMessages) == 0 && len(diff.OtherUpdates) == 0 && diff.AvailableMinID == 0 { + if len(diff.Events) == 0 && len(diff.NewMessages) == 0 && len(diff.OtherUpdates) == 0 { return &tg.UpdatesChannelDifferenceEmpty{ Final: diff.Final, Pts: diff.Pts, @@ -148,12 +148,6 @@ func tgChannelDifference(viewerUserID int64, diff domain.ChannelDifference) tg.U updates = append(updates, update) } } - if diff.AvailableMinID > 0 { - updates = append(updates, &tg.UpdateChannelAvailableMessages{ - ChannelID: diff.Channel.ID, - AvailableMinID: diff.AvailableMinID, - }) - } chats := tgChannelDifferenceChats(viewerUserID, diff) users := tgUsersForViewer(viewerUserID, diff.Users) return &tg.UpdatesChannelDifference{