GODT-1993: Use more efficient filtering for message deletion

This commit is contained in:
James Houlahan 2022-11-01 17:11:07 +01:00
parent 048a83c8c9
commit 75b788b793
4 changed files with 33 additions and 27 deletions

2
go.mod
View File

@ -39,7 +39,7 @@ require (
github.com/stretchr/testify v1.8.0
github.com/urfave/cli/v2 v2.20.3
github.com/vmihailenco/msgpack/v5 v5.3.5
gitlab.protontech.ch/go/liteapi v0.38.1-0.20221101102120-060b4bbab844
gitlab.protontech.ch/go/liteapi v0.39.2
go.uber.org/goleak v1.2.0
golang.org/x/exp v0.0.0-20221023144134-a1e5550cf13e
golang.org/x/net v0.1.0

4
go.sum
View File

@ -403,8 +403,8 @@ github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsr
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/zclconf/go-cty v1.11.0 h1:726SxLdi2SDnjY+BStqB9J1hNp4+2WlzyXLuimibIe0=
github.com/zclconf/go-cty v1.11.0/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA=
gitlab.protontech.ch/go/liteapi v0.38.1-0.20221101102120-060b4bbab844 h1:HmWG1P2qhImVjx0mFMuwfBj6xmGjLzb3ZiUwe2wc8pg=
gitlab.protontech.ch/go/liteapi v0.38.1-0.20221101102120-060b4bbab844/go.mod h1:IM7ADWjgIL2hXopzx0WNamizEuMgM2QZl7QH12FNflk=
gitlab.protontech.ch/go/liteapi v0.39.2 h1:HWxuO6c9cnRAzpLaj2SrOD1jJEWVa4nAUH1TkVPA4t4=
gitlab.protontech.ch/go/liteapi v0.39.2/go.mod h1:IM7ADWjgIL2hXopzx0WNamizEuMgM2QZl7QH12FNflk=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=

View File

@ -30,6 +30,7 @@ import (
"github.com/ProtonMail/proton-bridge/v2/internal/vault"
"github.com/ProtonMail/proton-bridge/v2/pkg/message"
"github.com/bradenaw/juniper/stream"
"github.com/bradenaw/juniper/xslices"
"gitlab.protontech.ch/go/liteapi"
"golang.org/x/exp/slices"
)
@ -308,26 +309,30 @@ func (conn *imapConnector) RemoveMessagesFromMailbox(ctx context.Context, messag
}
if mailboxID == liteapi.SpamLabel || mailboxID == liteapi.TrashLabel {
// check if messages are only in Trash and AllMail before they are permanently deleted.
var messagesToDelete []string
var metadata []liteapi.MessageMetadata
// GODT-1993 - Update to more efficient method.
for _, messageID := range messageIDs {
m, err := conn.client.GetMessage(ctx, string(messageID))
// There's currently no limit on how many IDs we can filter on,
// but to be nice to API, let's chunk it by 150.
for _, messageIDs := range xslices.Chunk(messageIDs, 150) {
m, err := conn.client.GetMessageMetadata(ctx, liteapi.MessageFilter{
ID: mapTo[imap.MessageID, string](messageIDs),
})
if err != nil {
return fmt.Errorf("failed to get message info")
return err
}
if len(m.LabelIDs) == 1 && m.LabelIDs[0] == liteapi.AllMailLabel {
messagesToDelete = append(messagesToDelete, m.ID)
}
m = xslices.Filter(m, func(m liteapi.MessageMetadata) bool {
return len(m.LabelIDs) == 1 && m.LabelIDs[0] == liteapi.AllMailLabel
})
metadata = append(metadata, m...)
}
if len(messagesToDelete) == 0 {
return nil
if err := conn.client.DeleteMessage(ctx, xslices.Map(metadata, func(m liteapi.MessageMetadata) string {
return m.ID
})...); err != nil {
return err
}
return conn.client.DeleteMessage(ctx, messagesToDelete...)
}
return nil

View File

@ -22,7 +22,6 @@ import (
"encoding/base64"
"fmt"
"net/mail"
"net/url"
"runtime"
"strings"
@ -143,15 +142,16 @@ func getParentID( //nolint:funlen
// Try to find a parent ID in the internal references.
for _, internal := range internal {
filter := url.Values{
"ID": {internal},
}
var addrID string
if addrMode == vault.SplitMode {
filter["AddressID"] = []string{authAddrID}
addrID = authAddrID
}
metadata, err := client.GetMessageMetadata(ctx, filter)
metadata, err := client.GetMessageMetadata(ctx, liteapi.MessageFilter{
ID: []string{internal},
AddressID: addrID,
})
if err != nil {
return "", fmt.Errorf("failed to get message metadata: %w", err)
}
@ -168,15 +168,16 @@ func getParentID( //nolint:funlen
// If no parent was found, try to find it in the last external reference.
// There can be multiple messages with the same external ID; in this case, we don't pick any parent.
if parentID == "" && len(external) > 0 {
filter := url.Values{
"ExternalID": {external[len(external)-1]},
}
var addrID string
if addrMode == vault.SplitMode {
filter["AddressID"] = []string{authAddrID}
addrID = authAddrID
}
metadata, err := client.GetMessageMetadata(ctx, filter)
metadata, err := client.GetMessageMetadata(ctx, liteapi.MessageFilter{
ExternalID: external[len(external)-1],
AddressID: addrID,
})
if err != nil {
return "", fmt.Errorf("failed to get message metadata: %w", err)
}