mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-10 12:46:46 +00:00
fix(GODT-2424): Sync Builder Message Split
Incorrect math was causing some messages to not be built and be missing from Gluon.
This commit is contained in:
@ -503,41 +503,7 @@ func syncMessages(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var expectedMemUsage uint64
|
chunks := chunkSyncBuilderBatch(buildBatch.batch, syncMaxMessageBuildingMem)
|
||||||
var chunks [][]proton.FullMessage
|
|
||||||
|
|
||||||
{
|
|
||||||
var lastIndex int
|
|
||||||
var index int
|
|
||||||
for _, v := range buildBatch.batch {
|
|
||||||
var dataSize uint64
|
|
||||||
for _, a := range v.Attachments {
|
|
||||||
dataSize += uint64(a.Size)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2x increase for attachment due to extra memory needed for decrypting and writing
|
|
||||||
// in memory buffer.
|
|
||||||
dataSize *= 2
|
|
||||||
dataSize += uint64(len(v.Body))
|
|
||||||
|
|
||||||
nextMemSize := expectedMemUsage + dataSize
|
|
||||||
if nextMemSize >= syncMaxMessageBuildingMem {
|
|
||||||
chunks = append(chunks, buildBatch.batch[lastIndex:index])
|
|
||||||
lastIndex = index
|
|
||||||
expectedMemUsage = dataSize
|
|
||||||
} else {
|
|
||||||
expectedMemUsage = nextMemSize
|
|
||||||
}
|
|
||||||
|
|
||||||
index++
|
|
||||||
}
|
|
||||||
|
|
||||||
if index < len(buildBatch.batch) {
|
|
||||||
chunks = append(chunks, buildBatch.batch[index:])
|
|
||||||
} else if index == len(buildBatch.batch) && len(chunks) == 0 {
|
|
||||||
chunks = [][]proton.FullMessage{buildBatch.batch}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for index, chunk := range chunks {
|
for index, chunk := range chunks {
|
||||||
logrus.Debugf("Build request: %v of %v count=%v", index, len(chunks), len(chunk))
|
logrus.Debugf("Build request: %v of %v count=%v", index, len(chunks), len(chunk))
|
||||||
@ -852,3 +818,39 @@ func (a *attachmentDownloader) getAttachments(ctx context.Context, attachments [
|
|||||||
func (a *attachmentDownloader) close() {
|
func (a *attachmentDownloader) close() {
|
||||||
a.cancel()
|
a.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func chunkSyncBuilderBatch(batch []proton.FullMessage, maxMemory uint64) [][]proton.FullMessage {
|
||||||
|
var expectedMemUsage uint64
|
||||||
|
var chunks [][]proton.FullMessage
|
||||||
|
var lastIndex int
|
||||||
|
var index int
|
||||||
|
|
||||||
|
for _, v := range batch {
|
||||||
|
var dataSize uint64
|
||||||
|
for _, a := range v.Attachments {
|
||||||
|
dataSize += uint64(a.Size)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2x increase for attachment due to extra memory needed for decrypting and writing
|
||||||
|
// in memory buffer.
|
||||||
|
dataSize *= 2
|
||||||
|
dataSize += uint64(len(v.Body))
|
||||||
|
|
||||||
|
nextMemSize := expectedMemUsage + dataSize
|
||||||
|
if nextMemSize >= maxMemory {
|
||||||
|
chunks = append(chunks, batch[lastIndex:index])
|
||||||
|
lastIndex = index
|
||||||
|
expectedMemUsage = dataSize
|
||||||
|
} else {
|
||||||
|
expectedMemUsage = nextMemSize
|
||||||
|
}
|
||||||
|
|
||||||
|
index++
|
||||||
|
}
|
||||||
|
|
||||||
|
if lastIndex < len(batch) {
|
||||||
|
chunks = append(chunks, batch[lastIndex:])
|
||||||
|
}
|
||||||
|
|
||||||
|
return chunks
|
||||||
|
}
|
||||||
|
|||||||
@ -24,6 +24,8 @@ import (
|
|||||||
|
|
||||||
"github.com/ProtonMail/gluon/imap"
|
"github.com/ProtonMail/gluon/imap"
|
||||||
"github.com/ProtonMail/gluon/rfc822"
|
"github.com/ProtonMail/gluon/rfc822"
|
||||||
|
"github.com/ProtonMail/go-proton-api"
|
||||||
|
"github.com/bradenaw/juniper/xslices"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -47,3 +49,32 @@ func TestNewFailedMessageLiteral(t *testing.T) {
|
|||||||
require.Equal(t, `("text" "plain" () NIL NIL "base64" 114 2)`, parsed.Body)
|
require.Equal(t, `("text" "plain" () NIL NIL "base64" 114 2)`, parsed.Body)
|
||||||
require.Equal(t, `("text" "plain" () NIL NIL "base64" 114 2 NIL NIL NIL NIL)`, parsed.Structure)
|
require.Equal(t, `("text" "plain" () NIL NIL "base64" 114 2 NIL NIL NIL NIL)`, parsed.Structure)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSyncChunkSyncBuilderBatch(t *testing.T) {
|
||||||
|
// GODT-2424 - Some messages were not fully built due to a bug in the chunking if the total memory used by the
|
||||||
|
// message would be higher than the maximum we allowed.
|
||||||
|
const totalMessageCount = 100
|
||||||
|
|
||||||
|
msg := proton.FullMessage{
|
||||||
|
Message: proton.Message{
|
||||||
|
Attachments: []proton.Attachment{
|
||||||
|
{
|
||||||
|
Size: int64(8 * Megabyte),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
AttData: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
messages := xslices.Repeat(msg, totalMessageCount)
|
||||||
|
|
||||||
|
chunks := chunkSyncBuilderBatch(messages, 16*Megabyte)
|
||||||
|
|
||||||
|
var totalMessagesInChunks int
|
||||||
|
|
||||||
|
for _, v := range chunks {
|
||||||
|
totalMessagesInChunks += len(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
require.Equal(t, totalMessagesInChunks, totalMessageCount)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user