Skip to content

Commit

Permalink
fix(GODT-2156): Use UUID instead of Integers for internal ID
Browse files Browse the repository at this point in the history
Avoids collision issues if users try to copy messages between different
Gluon based servers.
  • Loading branch information
LBeernaertProton committed Nov 25, 2022
1 parent 33e01d9 commit c337691
Show file tree
Hide file tree
Showing 32 changed files with 205 additions and 143 deletions.
2 changes: 1 addition & 1 deletion benchmarks/gluon_bench/store_benchmarks/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func (*Create) Run(ctx context.Context, st store.Store) (*reporter.BenchmarkRun,

for i := uint(0); i < *flags.StoreItemCount; i++ {
dc.Start()
err := s.Set(imap.InternalMessageID(uint64(i)), data)
err := s.Set(imap.NewInternalMessageID(), data)
dc.Stop()

if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/gluon_bench/store_benchmarks/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func CreateRandomState(st store.Store, count uint) ([]imap.InternalMessageID, er
data := make([]byte, *flags.StoreItemSize)

for i := uint(0); i < count; i++ {
uuid := imap.InternalMessageID(uint64(i))
uuid := imap.NewInternalMessageID()

if err := st.Set(uuid, data); err != nil {
return nil, err
Expand Down
27 changes: 13 additions & 14 deletions imap/strong_types.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package imap

import (
"encoding/binary"
"fmt"
"strconv"

"github.com/ProtonMail/gluon/internal/utils"
"github.com/google/uuid"
)

type MailboxID string
Expand All @@ -20,7 +20,9 @@ func (m MessageID) ShortID() string {
return utils.ShortID(string(m))
}

type InternalMessageID uint64
type InternalMessageID struct {
uuid.UUID
}

type InternalMailboxID uint64

Expand All @@ -29,31 +31,28 @@ func (i InternalMailboxID) ShortID() string {
}

func (i InternalMessageID) ShortID() string {
return strconv.FormatUint(uint64(i), 10)
return utils.ShortID(i.String())
}

func (i InternalMailboxID) String() string {
return strconv.FormatUint(uint64(i), 10)
}

func (i InternalMessageID) String() string {
return strconv.FormatUint(uint64(i), 10)
return i.UUID.String()
}

func NewInternalMessageID() InternalMessageID {
return InternalMessageID{UUID: uuid.New()}
}

func InternalMessageIDFromString(id string) (InternalMessageID, error) {
num, err := strconv.ParseUint(id, 10, 64)
num, err := uuid.Parse(id)
if err != nil {
return 0, fmt.Errorf("invalid message id:%w", err)
return InternalMessageID{}, fmt.Errorf("invalid message id:%w", err)
}

return InternalMessageID(num), nil
}

func (i InternalMessageID) ToBytes() []byte {
bytes := make([]byte, 8)
binary.LittleEndian.PutUint64(bytes, uint64(i))

return bytes
return InternalMessageID{UUID: num}, nil
}

type UID uint32
Expand Down
4 changes: 2 additions & 2 deletions internal/backend/connector_updates.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ func (user *user) applyMessagesCreated(ctx context.Context, update *imap.Message
continue
}

internalID = user.nextMessageID()
internalID = imap.NewInternalMessageID()

literal, err := rfc822.SetHeaderValue(message.Literal, ids.InternalIDKey, internalID.String())
if err != nil {
Expand Down Expand Up @@ -597,7 +597,7 @@ func (user *user) applyMessageUpdated(ctx context.Context, update *imap.MessageU
}
// create new entry
{
newInternalID := user.nextMessageID()
newInternalID := imap.NewInternalMessageID()
literal, err := rfc822.SetHeaderValue(update.Literal, ids.InternalIDKey, newInternalID.String())
if err != nil {
return fmt.Errorf("failed to set internal ID: %w", err)
Expand Down
4 changes: 2 additions & 2 deletions internal/backend/state_connector_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@ func (sc *stateConnectorImpl) CreateMessage(

msg, newLiteral, err := sc.connector.CreateMessage(ctx, mboxID, literal, flags, date)
if err != nil {
return 0, imap.Message{}, nil, err
return imap.InternalMessageID{}, imap.Message{}, nil, err
}

return sc.user.nextMessageID(), msg, newLiteral, nil
return imap.NewInternalMessageID(), msg, newLiteral, nil
}

func (sc *stateConnectorImpl) AddMessagesToMailbox(
Expand Down
4 changes: 0 additions & 4 deletions internal/backend/state_user_interface_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,3 @@ func (s *StateUserInterfaceImpl) GetRecoveryMailboxID() ids.MailboxIDPair {
RemoteID: ids.GluonInternalRecoveryMailboxRemoteID,
}
}

func (s *StateUserInterfaceImpl) NextRecoveryMessageID() imap.InternalMessageID {
return s.u.nextMessageID()
}
16 changes: 0 additions & 16 deletions internal/backend/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"fmt"
"sync"
"sync/atomic"

"github.com/ProtonMail/gluon/connector"
"github.com/ProtonMail/gluon/imap"
Expand Down Expand Up @@ -37,7 +36,6 @@ type user struct {
updateWG sync.WaitGroup
updateQuitCh chan struct{}

messageIDCounter uint64
globalUIDValidity imap.UID

recoveryMailboxID imap.InternalMailboxID
Expand Down Expand Up @@ -68,15 +66,6 @@ func newUser(

return db.GetOrCreateMailbox(ctx, tx, mbox, delimiter, conn.GetUIDValidity())
})

if err != nil {
return nil, err
}

// Get the last message ID from the database so we can resume our counter properly.
highestMessageID, err := db.ReadResult(ctx, database, func(ctx context.Context, client *ent.Client) (imap.InternalMessageID, error) {
return db.GetHighestMessageID(ctx, client)
})
if err != nil {
return nil, err
}
Expand All @@ -93,7 +82,6 @@ func newUser(

states: make(map[state.StateID]*state.State),
updateQuitCh: make(chan struct{}),
messageIDCounter: uint64(highestMessageID),
globalUIDValidity: conn.GetUIDValidity(),

recoveryMailboxID: recoveryMBox.ID,
Expand Down Expand Up @@ -311,10 +299,6 @@ func (user *user) closeStates() {
}
}

func (user *user) nextMessageID() imap.InternalMessageID {
return imap.InternalMessageID(atomic.AddUint64(&user.messageIDCounter, 1))
}

func (user *user) cleanupStaleStoreData(ctx context.Context) error {
storeIds, err := user.store.List()
if err != nil {
Expand Down
10 changes: 6 additions & 4 deletions internal/db/ent/message.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 8 additions & 9 deletions internal/db/ent/message_create.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion internal/db/ent/message_delete.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion internal/db/ent/message_query.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions internal/db/ent/message_update.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions internal/db/ent/messageflag.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion internal/db/ent/messageflag_create.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions internal/db/ent/messageflag_update.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions internal/db/ent/migrate/schema.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion internal/db/ent/schema/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type Message struct {
// Fields of the Message.
func (Message) Fields() []ent.Field {
return []ent.Field{
field.Uint64("id").GoType(imap.InternalMessageID(0)).Unique().Immutable(),
field.UUID("id", imap.NewInternalMessageID()).Unique().Immutable(),
field.String("RemoteID").Optional().Unique().GoType(imap.MessageID("")),
field.Time("Date"),
field.Int("Size"),
Expand Down
Loading

0 comments on commit c337691

Please sign in to comment.