Compare commits

...

2 Commits

Author SHA1 Message Date
53f28bcbec chore: Umshiang Bridge 3.5.4 changelog. 2023-10-18 15:32:49 +02:00
89f7878910 fix(GODT-3033): Unable to receive new mail
If the IMAP service happened to finish syncing and wanted to reset the
user event service at a time the latter was publishing an event a
deadlock would occur and the user would not receive any new messages.

This change puts the request to revert the event id in a separate
go-routine to avoid this situation from re-occurring. The operational
flow remains unchanged as the event service will only process this
request once the current set of events have been published.
2023-10-18 14:45:29 +02:00
3 changed files with 31 additions and 19 deletions

View File

@ -3,6 +3,12 @@
Changelog [format](http://keepachangelog.com/en/1.0.0/) Changelog [format](http://keepachangelog.com/en/1.0.0/)
## Umshiang Bridge 3.5.4
### Fixed
* GODT-3033: Unable to receive new mail.
## Umshiang Bridge 3.5.3 ## Umshiang Bridge 3.5.3
### Changed ### 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 .PHONY: build build-gui build-nogui build-launcher versioner hasher
# Keep version hardcoded so app build works also without Git repository. # Keep version hardcoded so app build works also without Git repository.
BRIDGE_APP_VERSION?=3.5.3+git BRIDGE_APP_VERSION?=3.5.4+git
APP_VERSION:=${BRIDGE_APP_VERSION} APP_VERSION:=${BRIDGE_APP_VERSION}
APP_FULL_NAME:=Proton Mail Bridge APP_FULL_NAME:=Proton Mail Bridge
APP_VENDOR:=Proton AG APP_VENDOR:=Proton AG

View File

@ -22,6 +22,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"path/filepath" "path/filepath"
"sync/atomic"
"time" "time"
"github.com/ProtonMail/gluon/async" "github.com/ProtonMail/gluon/async"
@ -94,7 +95,7 @@ type Service struct {
syncConfigPath string syncConfigPath string
lastHandledEventID string lastHandledEventID string
isSyncing bool isSyncing atomic.Bool
} }
func NewService( func NewService(
@ -405,10 +406,14 @@ func (s *Service) run(ctx context.Context) { //nolint gocyclo
continue continue
} }
// Start a goroutine to wait on event reset as it is possible that the sync received message
// was processed during an event publish. This in turn will block the imap service, since the
// event service is unable to reply to the request until the events have been processed.
s.log.Info("Sync complete, starting API event stream") s.log.Info("Sync complete, starting API event stream")
go func() {
if err := s.eventProvider.RewindEventID(ctx, s.lastHandledEventID); err != nil { if err := s.eventProvider.RewindEventID(ctx, s.lastHandledEventID); err != nil {
if errors.Is(err, context.Canceled) { if errors.Is(err, context.Canceled) {
continue return
} }
s.log.WithError(err).Error("Failed to rewind event service") s.log.WithError(err).Error("Failed to rewind event service")
@ -421,7 +426,8 @@ func (s *Service) run(ctx context.Context) { //nolint gocyclo
}) })
} }
s.isSyncing = false s.isSyncing.Store(false)
}()
} }
case request, ok := <-s.syncUpdateApplier.requestCh: case request, ok := <-s.syncUpdateApplier.requestCh:
@ -443,7 +449,7 @@ func (s *Service) run(ctx context.Context) { //nolint gocyclo
continue continue
} }
e.Consume(func(event proton.Event) error { e.Consume(func(event proton.Event) error {
if s.isSyncing { if s.isSyncing.Load() {
if err := syncEventHandler.OnEvent(ctx, event); err != nil { if err := syncEventHandler.OnEvent(ctx, event); err != nil {
return err return err
} }
@ -615,13 +621,13 @@ func (s *Service) setShowAllMail(v bool) {
} }
func (s *Service) startSyncing() { func (s *Service) startSyncing() {
s.isSyncing = true s.isSyncing.Store(true)
s.syncHandler.Execute(s.syncReporter, s.labels.GetLabelMap(), s.syncUpdateApplier, s.syncMessageBuilder, syncservice.DefaultRetryCoolDown) s.syncHandler.Execute(s.syncReporter, s.labels.GetLabelMap(), s.syncUpdateApplier, s.syncMessageBuilder, syncservice.DefaultRetryCoolDown)
} }
func (s *Service) cancelSync() { func (s *Service) cancelSync() {
s.syncHandler.CancelAndWait() s.syncHandler.CancelAndWait()
s.isSyncing = false s.isSyncing.Store(false)
} }
type resyncReq struct{} type resyncReq struct{}