Compare commits

..

10 Commits

Author SHA1 Message Date
71d7deb3b1 chore: Bridge Quebec 3.1.3 changelog 2023-05-09 11:36:35 +02:00
5630b7d2e6 fix(GODT-2616): Silence UID of order report
https://github.com/ProtonMail/gluon/pull/347
2023-05-08 10:27:37 +02:00
2ee4893325 fix(GODT-2614): Handle failed update during sync
The sync process was getting stuck since we never handled the case where
the update to Gluon failed. This caused the flush stage to exist, but
the sync process would continue until it eventually gets stuck due to
lack of progress.
2023-05-08 09:40:53 +02:00
2f7f898cee fix(GODT-2582): fix hash for changed boundary. 2023-04-26 14:00:45 +02:00
8d53ee855b chore: Bridge Quebec 3.1.2 changelog 2023-04-25 13:06:58 +02:00
ec0db47f32 fix(GODT-2582): Dedup recovered messages folder
same code as:
    * https://github.com/ProtonMail/gluon/pull/338
    * https://github.com/ProtonMail/gluon/pull/339
2023-04-25 11:36:21 +02:00
6fcea2ad83 chore: Bridge Quebec 3.1.1 changelog 2023-04-11 14:31:39 +02:00
098f294cac fix(GODT-2573): Crash on null update
Ensure that if we don't produce an update we don't construct an update
array with nil values.
2023-04-11 10:36:26 +02:00
a6f5cc870c fix(GODT-2500): pass handler pointer down the road. 2023-04-06 16:39:29 +02:00
7330406752 fix(GODT-2500): Recover in deferred function. 2023-04-05 09:25:24 +02:00
20 changed files with 131 additions and 86 deletions

View File

@ -2,6 +2,25 @@
Changelog [format](http://keepachangelog.com/en/1.0.0/)
## [Bridge 3.1.3] Quebec
### Changed
* GODT-2616: Silence UID of order report.
* GODT-2614: Handle failed update during sync.
## [Bridge 3.1.2] Quebec
### Changed
* GODT-2582 Dedup recovered messages folder.
## [Bridge 3.1.1] Quebec
### Fixed
* GODT-2500: Fix handler passing.
## [Bridge 3.1.0] Quebec
### Changed

View File

@ -11,7 +11,7 @@ ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
.PHONY: build build-gui build-nogui build-launcher versioner hasher
# Keep version hardcoded so app build works also without Git repository.
BRIDGE_APP_VERSION?=3.1.0+git
BRIDGE_APP_VERSION?=3.1.3+git
APP_VERSION:=${BRIDGE_APP_VERSION}
APP_FULL_NAME:=Proton Mail Bridge
APP_VENDOR:=Proton AG
@ -325,7 +325,11 @@ run-nogui: build-nogui clean-vendor gofiles
PROTONMAIL_ENV=dev ./${LAUNCHER_EXE} ${RUN_FLAGS} -c
run-debug:
dlv debug ./cmd/Desktop-Bridge/main.go -- -l=debug
dlv debug \
--build-flags "-ldflags '-X github.com/ProtonMail/proton-bridge/v3/internal/constants.Version=3.1.0+git'" \
./cmd/Desktop-Bridge/main.go \
-- \
-n -l=trace
ifeq "${TARGET_OS}" "windows"
EXE_SUFFIX=.exe

View File

@ -25,6 +25,7 @@ import (
"time"
"github.com/Masterminds/semver/v3"
"github.com/ProtonMail/gluon/async"
"github.com/ProtonMail/gopenpgp/v2/crypto"
"github.com/ProtonMail/proton-bridge/v3/internal/constants"
"github.com/ProtonMail/proton-bridge/v3/internal/crash"
@ -62,7 +63,7 @@ func main() { //nolint:funlen
reporter := sentry.NewReporter(appName, useragent.New())
crashHandler := crash.NewHandler(reporter.ReportException)
defer crashHandler.HandlePanic()
defer async.HandlePanic(crashHandler)
locationsProvider, err := locations.NewDefaultProvider(filepath.Join(constants.VendorName, constants.ConfigName))
if err != nil {

4
go.mod
View File

@ -5,9 +5,9 @@ go 1.18
require (
github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557
github.com/Masterminds/semver/v3 v3.2.0
github.com/ProtonMail/gluon v0.15.1-0.20230331095629-e23a7a1be2a8
github.com/ProtonMail/gluon v0.15.1-0.20230508082626-2467e0b45ed9
github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a
github.com/ProtonMail/go-proton-api v0.4.1-0.20230331115846-7ba084061eaa
github.com/ProtonMail/go-proton-api v0.4.1-0.20230406143739-c7596e170799
github.com/ProtonMail/gopenpgp/v2 v2.5.2
github.com/PuerkitoBio/goquery v1.8.1
github.com/abiosoft/ishell v2.0.0+incompatible

8
go.sum
View File

@ -28,8 +28,8 @@ github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf h1:yc9daCCYUefEs
github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo=
github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk=
github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g=
github.com/ProtonMail/gluon v0.15.1-0.20230331095629-e23a7a1be2a8 h1:USMR8imbxkP4Ailch4ceV3hCZTaANMIGHhb5rpZFYn4=
github.com/ProtonMail/gluon v0.15.1-0.20230331095629-e23a7a1be2a8/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI=
github.com/ProtonMail/gluon v0.15.1-0.20230508082626-2467e0b45ed9 h1:UwxjrPVOgyLLSVFhnxkpXLItowNzGGacqwVCp01wn6E=
github.com/ProtonMail/gluon v0.15.1-0.20230508082626-2467e0b45ed9/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI=
github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4=
github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4=
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
@ -40,8 +40,8 @@ github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753 h1:I8IsYA297
github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753/go.mod h1:NBAn21zgCJ/52WLDyed18YvYFm5tEoeDauubFqLokM4=
github.com/ProtonMail/go-mime v0.0.0-20221031134845-8fd9bc37cf08 h1:dS7r5z4iGS0qCjM7UwWdsEMzQesUQbGcXdSm2/tWboA=
github.com/ProtonMail/go-mime v0.0.0-20221031134845-8fd9bc37cf08/go.mod h1:qRZgbeASl2a9OwmsV85aWwRqic0NHPh+9ewGAzb4cgM=
github.com/ProtonMail/go-proton-api v0.4.1-0.20230331115846-7ba084061eaa h1:0JKWkz/gIYf+eky0dCFeBWrjEDLf59lS8HOlXtvn6Nk=
github.com/ProtonMail/go-proton-api v0.4.1-0.20230331115846-7ba084061eaa/go.mod h1:RfpLBcTIhfjOIcBhh7f36LtAOEi0mqPd3t8gyLWmCZM=
github.com/ProtonMail/go-proton-api v0.4.1-0.20230406143739-c7596e170799 h1:slk4Drrkij1EVTnFOlIDyJsfjt69tnw8w2g1NMb253U=
github.com/ProtonMail/go-proton-api v0.4.1-0.20230406143739-c7596e170799/go.mod h1:kis4GD6FHp1ZWnenSBepldt8ai+vYalDPeey9yGwyXk=
github.com/ProtonMail/go-srp v0.0.5 h1:xhUioxZgDbCnpo9JehyFhwwsn9JLWkUGfB0oiKXgiGg=
github.com/ProtonMail/go-srp v0.0.5/go.mod h1:06iYHtLXW8vjLtccWj++x3MKy65sIT8yZd7nrJF49rs=
github.com/ProtonMail/gopenpgp/v2 v2.5.2 h1:97SjlWNAxXl9P22lgwgrZRshQdiEfAht0g3ZoiA1GCw=

View File

@ -28,6 +28,7 @@ import (
"time"
"github.com/Masterminds/semver/v3"
"github.com/ProtonMail/gluon/async"
"github.com/ProtonMail/proton-bridge/v3/internal/bridge"
"github.com/ProtonMail/proton-bridge/v3/internal/constants"
"github.com/ProtonMail/proton-bridge/v3/internal/cookies"
@ -379,7 +380,7 @@ func withCrashHandler(restarter *restarter.Restarter, reporter *sentry.Reporter,
defer logrus.Debug("Crash handler stopped")
crashHandler := crash.NewHandler(crash.ShowErrorNotification(constants.FullAppName))
defer crashHandler.HandlePanic()
defer async.HandlePanic(crashHandler)
// On crash, send crash report to Sentry.
crashHandler.AddRecoveryAction(reporter.ReportException)

View File

@ -46,10 +46,11 @@ func runFrontend(
switch {
case c.Bool(flagCLI):
return bridgeCLI.New(bridge, restarter, eventCh, crashHandler).Loop()
return bridgeCLI.New(bridge, restarter, eventCh, crashHandler, quitCh).Loop()
case c.Bool(flagNonInteractive):
select {}
<-quitCh
return nil
case c.Bool(flagGRPC):
service, err := grpc.NewService(crashHandler, restarter, locations, bridge, eventCh, quitCh, !c.Bool(flagNoWindow), parentPID)

View File

@ -40,7 +40,7 @@ func checkSingleInstance(settingPath, lockFilePath string, curVersion *semver.Ve
return lock, nil
}
logrus.Debug("Failed to create lock file; another instance is running")
logrus.Warn("Failed to create lock file; another instance is running")
// We couldn't create the lock file, so another instance is probably running.
// Check if it's an older version of the app.

View File

@ -45,7 +45,7 @@ func NewMocks(tb testing.TB, version, minAuto *semver.Version) *Mocks {
mocks.TLSReporter.EXPECT().GetTLSIssueCh().Return(mocks.TLSIssueCh).AnyTimes()
// This is called at he end of any go-routine:
mocks.CrashHandler.EXPECT().HandlePanic().AnyTimes()
mocks.CrashHandler.EXPECT().HandlePanic(gomock.Any()).AnyTimes()
return mocks
}

View File

@ -1,5 +1,5 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/ProtonMail/proton-bridge/v3/internal/async (interfaces: PanicHandler)
// Source: github.com/ProtonMail/gluon/async (interfaces: PanicHandler)
// Package mocks is a generated GoMock package.
package mocks
@ -34,13 +34,13 @@ func (m *MockPanicHandler) EXPECT() *MockPanicHandlerMockRecorder {
}
// HandlePanic mocks base method.
func (m *MockPanicHandler) HandlePanic() {
func (m *MockPanicHandler) HandlePanic(arg0 interface{}) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "HandlePanic")
m.ctrl.Call(m, "HandlePanic", arg0)
}
// HandlePanic indicates an expected call of HandlePanic.
func (mr *MockPanicHandlerMockRecorder) HandlePanic() *gomock.Call {
func (mr *MockPanicHandlerMockRecorder) HandlePanic(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HandlePanic", reflect.TypeOf((*MockPanicHandler)(nil).HandlePanic))
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HandlePanic", reflect.TypeOf((*MockPanicHandler)(nil).HandlePanic), arg0)
}

View File

@ -38,14 +38,16 @@ func (h *Handler) AddRecoveryAction(action RecoveryAction) *Handler {
return h
}
func (h *Handler) HandlePanic() {
func (h *Handler) HandlePanic(r interface{}) {
sentry.SkipDuringUnwind()
if r := recover(); r != nil {
if r == nil {
return
}
for _, action := range h.actions {
if err := action(r); err != nil {
logrus.WithError(err).Error("Failed to execute recovery action")
}
}
}
}

View File

@ -21,10 +21,12 @@ import (
"fmt"
"testing"
"github.com/ProtonMail/gluon/async"
"github.com/stretchr/testify/assert"
)
func TestHandler(t *testing.T) {
assert.NotPanics(t, func() {
var s string
h := NewHandler(
@ -52,7 +54,8 @@ func TestHandler(t *testing.T) {
assert.Equal(t, "1: thing\n2: thing\n3: thing\n4: thing\n", s)
}()
defer h.HandlePanic()
defer async.HandlePanic(h)
panic("thing")
})
}

View File

@ -45,7 +45,13 @@ type frontendCLI struct {
}
// New returns a new CLI frontend configured with the given options.
func New(bridge *bridge.Bridge, restarter *restarter.Restarter, eventCh <-chan events.Event, panicHandler async.PanicHandler) *frontendCLI { //nolint:revive
func New(
bridge *bridge.Bridge,
restarter *restarter.Restarter,
eventCh <-chan events.Event,
panicHandler async.PanicHandler,
quitCh <-chan struct{},
) *frontendCLI { //nolint:revive
fe := &frontendCLI{
Shell: ishell.New(),
bridge: bridge,
@ -285,6 +291,11 @@ func New(bridge *bridge.Bridge, restarter *restarter.Restarter, eventCh <-chan e
go fe.watchEvents(eventCh)
go func() {
<-quitCh
fe.Close()
}()
return fe
}

View File

@ -70,7 +70,7 @@ type Service struct { // nolint:structcheck
eventQueue []*StreamEvent
eventQueueMutex sync.Mutex
panicHandler CrashHandler
panicHandler async.PanicHandler
restarter Restarter
bridge *bridge.Bridge
eventCh <-chan events.Event
@ -97,7 +97,7 @@ type Service struct { // nolint:structcheck
// NewService returns a new instance of the service.
func NewService(
panicHandler CrashHandler,
panicHandler async.PanicHandler,
restarter Restarter,
locations service.Locator,
bridge *bridge.Bridge,
@ -192,10 +192,6 @@ func NewService(
return s, nil
}
func (s *Service) handlePanic() {
async.HandlePanic(s.panicHandler)
}
func (s *Service) initAutostart() {
s.firstTimeAutostart.Do(func() {
shouldAutostartBeOn := s.bridge.GetAutostart()
@ -213,13 +209,13 @@ func (s *Service) Loop() error {
s.log.Info("Not monitoring parent PID")
} else {
go func() {
defer s.handlePanic()
defer async.HandlePanic(s.panicHandler)
s.monitorParentPID()
}()
}
go func() {
defer s.handlePanic()
defer async.HandlePanic(s.panicHandler)
s.watchEvents()
}()
@ -229,7 +225,7 @@ func (s *Service) Loop() error {
defer close(doneCh)
go func() {
defer s.handlePanic()
defer async.HandlePanic(s.panicHandler)
select {
case <-s.quitCh:
@ -577,7 +573,7 @@ func (s *Service) monitorParentPID() {
s.log.Info("Parent process does not exist anymore. Initiating shutdown")
// quit will write to the parentPIDDoneCh, so we launch a goroutine.
go func() {
defer s.handlePanic()
defer async.HandlePanic(s.panicHandler)
if err := s.quit(); err != nil {
logrus.WithError(err).Error("Error on quit")

View File

@ -26,6 +26,7 @@ import (
"runtime"
"github.com/Masterminds/semver/v3"
"github.com/ProtonMail/gluon/async"
"github.com/ProtonMail/go-proton-api"
"github.com/ProtonMail/proton-bridge/v3/internal/bridge"
"github.com/ProtonMail/proton-bridge/v3/internal/constants"
@ -114,7 +115,7 @@ func (s *Service) Quit(ctx context.Context, empty *emptypb.Empty) (*emptypb.Empt
func (s *Service) quit() error {
// Windows is notably slow at Quitting. We do it in a goroutine to speed things up a bit.
go func() {
defer s.handlePanic()
defer async.HandlePanic(s.panicHandler)
if s.parentPID >= 0 {
s.parentPIDDoneCh <- struct{}{}
@ -223,7 +224,7 @@ func (s *Service) TriggerReset(ctx context.Context, _ *emptypb.Empty) (*emptypb.
s.log.Debug("TriggerReset")
go func() {
defer s.handlePanic()
defer async.HandlePanic(s.panicHandler)
s.triggerReset()
}()
@ -319,7 +320,7 @@ func (s *Service) ReportBug(ctx context.Context, report *ReportBugRequest) (*emp
}).Debug("ReportBug")
go func() {
defer s.handlePanic()
defer async.HandlePanic(s.panicHandler)
defer func() { _ = s.SendEvent(NewReportBugFinishedEvent()) }()
@ -348,7 +349,7 @@ func (s *Service) ExportTLSCertificates(_ context.Context, folderPath *wrappersp
s.log.WithField("folderPath", folderPath).Info("ExportTLSCertificates")
go func() {
defer s.handlePanic()
defer async.HandlePanic(s.panicHandler)
cert, key := s.bridge.GetBridgeTLSCert()
@ -384,7 +385,7 @@ func (s *Service) Login(ctx context.Context, login *LoginRequest) (*emptypb.Empt
s.log.WithField("username", login.Username).Debug("Login")
go func() {
defer s.handlePanic()
defer async.HandlePanic(s.panicHandler)
password, err := base64Decode(login.Password)
if err != nil {
@ -440,7 +441,7 @@ func (s *Service) Login2FA(ctx context.Context, login *LoginRequest) (*emptypb.E
s.log.WithField("username", login.Username).Debug("Login2FA")
go func() {
defer s.handlePanic()
defer async.HandlePanic(s.panicHandler)
if s.auth.UID == "" || s.authClient == nil {
s.log.Errorf("Login 2FA: authethication incomplete %s %p", s.auth.UID, s.authClient)
@ -485,7 +486,7 @@ func (s *Service) Login2Passwords(ctx context.Context, login *LoginRequest) (*em
s.log.WithField("username", login.Username).Debug("Login2Passwords")
go func() {
defer s.handlePanic()
defer async.HandlePanic(s.panicHandler)
password, err := base64Decode(login.Password)
if err != nil {
@ -507,7 +508,7 @@ func (s *Service) LoginAbort(ctx context.Context, loginAbort *LoginAbortRequest)
s.log.WithField("username", loginAbort.Username).Debug("LoginAbort")
go func() {
defer s.handlePanic()
defer async.HandlePanic(s.panicHandler)
s.loginAbort()
}()
@ -519,7 +520,7 @@ func (s *Service) CheckUpdate(context.Context, *emptypb.Empty) (*emptypb.Empty,
s.log.Debug("CheckUpdate")
go func() {
defer s.handlePanic()
defer async.HandlePanic(s.panicHandler)
updateCh, done := s.bridge.GetEvents(
events.UpdateAvailable{},
@ -551,7 +552,7 @@ func (s *Service) InstallUpdate(ctx context.Context, _ *emptypb.Empty) (*emptypb
s.log.Debug("InstallUpdate")
go func() {
defer s.handlePanic()
defer async.HandlePanic(s.panicHandler)
safe.RLock(func() {
s.bridge.InstallUpdate(s.target)
@ -592,7 +593,7 @@ func (s *Service) SetDiskCachePath(ctx context.Context, newPath *wrapperspb.Stri
s.log.WithField("path", newPath.Value).Debug("setDiskCachePath")
go func() {
defer s.handlePanic()
defer async.HandlePanic(s.panicHandler)
defer func() {
_ = s.SendEvent(NewDiskCachePathChangeFinishedEvent())
@ -659,7 +660,7 @@ func (s *Service) SetMailServerSettings(_ context.Context, settings *ImapSmtpSet
Debug("SetConnectionMode")
go func() {
defer s.handlePanic()
defer async.HandlePanic(s.panicHandler)
defer func() { _ = s.SendEvent(NewChangeMailServerSettingsFinishedEvent()) }()

View File

@ -20,6 +20,7 @@ package grpc
import (
"context"
"github.com/ProtonMail/gluon/async"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/emptypb"
@ -49,7 +50,7 @@ func (s *Service) RunEventStream(request *EventStreamRequest, server Bridge_RunE
// if events occurred before streaming started, they've been queued. Now that the stream channel is available
// we can flush the queued
go func() {
defer s.handlePanic()
defer async.HandlePanic(s.panicHandler)
s.eventQueueMutex.Lock()
defer s.eventQueueMutex.Unlock()

View File

@ -20,6 +20,7 @@ package grpc
import (
"context"
"github.com/ProtonMail/gluon/async"
"github.com/ProtonMail/proton-bridge/v3/internal/vault"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
@ -70,7 +71,7 @@ func (s *Service) SetUserSplitMode(ctx context.Context, splitMode *UserSplitMode
}
go func() {
defer s.handlePanic()
defer async.HandlePanic(s.panicHandler)
defer func() { _ = s.SendEvent(NewUserToggleSplitModeFinishedEvent(splitMode.UserID)) }()
var targetMode vault.AddressMode
@ -121,7 +122,7 @@ func (s *Service) LogoutUser(ctx context.Context, userID *wrapperspb.StringValue
}
go func() {
defer s.handlePanic()
defer async.HandlePanic(s.panicHandler)
if err := s.bridge.LogoutUser(context.Background(), userID.Value); err != nil {
s.log.WithError(err).Error("Failed to log user out")
@ -135,7 +136,7 @@ func (s *Service) RemoveUser(ctx context.Context, userID *wrapperspb.StringValue
s.log.WithField("UserID", userID.Value).Debug("RemoveUser")
go func() {
defer s.handlePanic()
defer async.HandlePanic(s.panicHandler)
// remove preferences
if err := s.bridge.DeleteUser(context.Background(), userID.Value); err != nil {

View File

@ -17,10 +17,6 @@
package grpc
type CrashHandler interface {
HandlePanic()
}
type Restarter interface {
Set(restart, crash bool)
AddFlags(flags ...string)

View File

@ -635,6 +635,10 @@ func (user *User) handleCreateMessageEvent(ctx context.Context, message proton.M
return nil, err
}
if update == nil {
return nil, nil
}
return []imap.Update{update}, nil
}, user.apiUserLock, user.apiAddrsLock, user.apiLabelsLock, user.updateChLock)
}

View File

@ -370,7 +370,7 @@ func (user *User) syncMessages(
errorCh := make(chan error, maxParallelDownloads*4)
// Go routine in charge of downloading message metadata
logging.GoAnnotated(ctx, user.panicHandler, func(ctx context.Context) {
async.GoAnnotated(ctx, user.panicHandler, func(ctx context.Context) {
defer close(downloadCh)
const MetadataDataPageSize = 150
@ -433,7 +433,7 @@ func (user *User) syncMessages(
}, logging.Labels{"sync-stage": "meta-data"})
// Goroutine in charge of downloading and building messages in maxBatchSize batches.
logging.GoAnnotated(ctx, user.panicHandler, func(ctx context.Context) {
async.GoAnnotated(ctx, user.panicHandler, func(ctx context.Context) {
defer close(buildCh)
defer close(errorCh)
defer func() {
@ -492,7 +492,7 @@ func (user *User) syncMessages(
}, logging.Labels{"sync-stage": "download"})
// Goroutine which builds messages after they have been downloaded
logging.GoAnnotated(ctx, user.panicHandler, func(ctx context.Context) {
async.GoAnnotated(ctx, user.panicHandler, func(ctx context.Context) {
defer close(flushCh)
defer func() {
logrus.Debugf("sync builder exit")
@ -530,7 +530,7 @@ func (user *User) syncMessages(
}, logging.Labels{"sync-stage": "builder"})
// Goroutine which converts the messages into updates and builds a waitable structure for progress tracking.
logging.GoAnnotated(ctx, user.panicHandler, func(ctx context.Context) {
async.GoAnnotated(ctx, user.panicHandler, func(ctx context.Context) {
defer close(flushUpdateCh)
defer func() {
logrus.Debugf("sync flush exit")
@ -610,6 +610,10 @@ func (user *User) syncMessages(
}, logging.Labels{"sync-stage": "flush"})
for flushUpdate := range flushUpdateCh {
if flushUpdate.err != nil {
return flushUpdate.err
}
if err := vault.SetLastMessageID(flushUpdate.messageID); err != nil {
return fmt.Errorf("failed to set last synced message ID: %w", err)
}
@ -780,7 +784,7 @@ func (user *User) newAttachmentDownloader(ctx context.Context, client *proton.Cl
ctx, cancel := context.WithCancel(ctx)
for i := 0; i < workerCount; i++ {
workerCh = make(chan attachmentJob)
logging.GoAnnotated(ctx, user.panicHandler, func(ctx context.Context) { attachmentWorker(ctx, client, workerCh) }, logging.Labels{
async.GoAnnotated(ctx, user.panicHandler, func(ctx context.Context) { attachmentWorker(ctx, client, workerCh) }, logging.Labels{
"sync": fmt.Sprintf("att-downloader %v", i),
})
}