forked from Silverfish/proton-bridge
feat(GODT-2442): handle bad event resync resolution.
This commit is contained in:
@ -142,21 +142,47 @@ func (bridge *Bridge) handleUserDeauth(ctx context.Context, user *user.User) {
|
||||
|
||||
func (bridge *Bridge) handleUserBadEvent(ctx context.Context, user *user.User, event events.UserBadEvent) {
|
||||
safe.Lock(func() {
|
||||
if rerr := bridge.reporter.ReportMessageWithContext("Failed to handle event", reporter.Context{
|
||||
reportContext := reporter.Context{
|
||||
"user_id": user.ID(),
|
||||
"old_event_id": event.OldEventID,
|
||||
"new_event_id": event.NewEventID,
|
||||
"event_info": event.EventInfo,
|
||||
"error": event.Error,
|
||||
"error_type": fmt.Sprintf("%T", internal.ErrCause(event.Error)),
|
||||
}); rerr != nil {
|
||||
logrus.WithError(rerr).Error("Failed to report failed event handling")
|
||||
}
|
||||
|
||||
bridge.logoutUser(ctx, user, true, false)
|
||||
// blockEventsIMAPandSMTP()
|
||||
|
||||
if doResyc, err := bridge.getBadEventUserFeedback(); err != nil || !doResyc {
|
||||
if rerr := bridge.reporter.ReportMessageWithContext("Failed to handle event: logout", reportContext); rerr != nil {
|
||||
logrus.WithError(rerr).Error("Failed to report failed event handling")
|
||||
}
|
||||
|
||||
bridge.logoutUser(ctx, user, true, false)
|
||||
return
|
||||
}
|
||||
|
||||
if rerr := bridge.reporter.ReportMessageWithContext("Failed to handle event: repair", reportContext); rerr != nil {
|
||||
logrus.WithError(rerr).Error("Failed to report event handling failure")
|
||||
}
|
||||
|
||||
if syncErr := user.SyncEvent(ctx); syncErr != nil {
|
||||
reportContext["error"] = syncErr
|
||||
reportContext["error_type"] = fmt.Sprintf("%T", internal.ErrCause(syncErr))
|
||||
if rerr := bridge.reporter.ReportMessageWithContext("Failed to handle event: repair failed: logging out", reportContext); rerr != nil {
|
||||
logrus.WithError(rerr).Error("Failed to report repair failure")
|
||||
}
|
||||
|
||||
bridge.logoutUser(ctx, user, true, false)
|
||||
return
|
||||
}
|
||||
}, bridge.usersLock)
|
||||
}
|
||||
|
||||
func (bridge *Bridge) getBadEventUserFeedback() (doResyc bool, err error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (bridge *Bridge) handleUncategorizedErrorEvent(event events.UncategorizedEventError) {
|
||||
if rerr := bridge.reporter.ReportMessageWithContext("Failed to handle due to uncategorized error", reporter.Context{
|
||||
"error_type": fmt.Sprintf("%T", internal.ErrCause(event.Error)),
|
||||
|
||||
@ -86,12 +86,22 @@ func (user *User) handleRefreshEvent(ctx context.Context, refresh proton.Refresh
|
||||
l.WithError(err).Error("Failed to report refresh to sentry")
|
||||
}
|
||||
|
||||
// Cancel the event stream once this refresh is done.
|
||||
defer user.pollAbort.Abort()
|
||||
return user.SyncEvent(ctx)
|
||||
}
|
||||
|
||||
// Resync after the refresh.
|
||||
func (user *User) SyncEvent(ctx context.Context) error {
|
||||
// Cancel the event stream
|
||||
user.pollAbort.Abort() // ??? There was a defer here. But I think it's best to do this immediately, there is no reason to continue with polls while having re-sync.
|
||||
|
||||
// Re-sync messages after the user, address and label refresh.
|
||||
defer user.goSync()
|
||||
|
||||
// stop IMAP and SMTP
|
||||
|
||||
if err := user.vault.SetEventID(""); err != nil {
|
||||
return fmt.Errorf("failed to clean latest event ID: %w", err)
|
||||
}
|
||||
|
||||
return safe.LockRet(func() error {
|
||||
// Fetch latest user info.
|
||||
apiUser, err := user.client.GetUser(ctx)
|
||||
|
||||
@ -626,6 +626,17 @@ func (user *User) doEventPoll(ctx context.Context) error {
|
||||
user.eventLock.Lock()
|
||||
defer user.eventLock.Unlock()
|
||||
|
||||
eventID := user.vault.EventID()
|
||||
if eventID == "" {
|
||||
err := errors.New("current eventID is empty")
|
||||
user.eventCh.Enqueue(events.UncategorizedEventError{ // this might be bad event.. I hope sync is ongoing
|
||||
UserID: user.ID(),
|
||||
Error: err,
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
event, err := user.client.GetEvent(ctx, user.vault.EventID())
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get event (caused by %T): %w", internal.ErrCause(err), err)
|
||||
|
||||
Reference in New Issue
Block a user