Do not unpause event loop if other mailbox is still fetching

This commit is contained in:
Michal Horejsek
2020-12-07 14:14:45 +01:00
parent 3e9c4ba614
commit 5c58089fb7
3 changed files with 37 additions and 6 deletions

View File

@ -454,8 +454,8 @@ func (im *imapMailbox) ListMessages(isUID bool, seqSet *imap.SeqSet, items []ima
// EXPUNGE cannot be sent during listing and can come only from
// the event loop, so we prevent any server side update to avoid
// the problem.
im.storeUser.PauseEventLoop(true)
defer im.storeUser.PauseEventLoop(false)
im.user.pauseEventLoop()
defer im.user.unpauseEventLoop()
var markAsReadIDs []string
markAsReadMutex := &sync.Mutex{}

View File

@ -42,11 +42,9 @@ type imapUser struct {
currentAddressLowercase string
appendInProcess sync.WaitGroup
}
// This method should eventually no longer be necessary. Everything should go via store.
func (iu *imapUser) client() pmapi.Client {
return iu.user.GetTemporaryPMAPIClient()
eventLoopPausingCounter int
eventLoopPausingLocker sync.Locker
}
// newIMAPUser returns struct implementing go-imap/user interface.
@ -78,9 +76,41 @@ func newIMAPUser(
storeAddress: storeAddress,
currentAddressLowercase: strings.ToLower(address),
eventLoopPausingLocker: &sync.Mutex{},
}, err
}
// This method should eventually no longer be necessary. Everything should go via store.
func (iu *imapUser) client() pmapi.Client {
return iu.user.GetTemporaryPMAPIClient()
}
// pauseEventLoop pauses event loop and increases the number of mailboxes which
// is performing action forbidding event loop to run (such as FETCH which needs
// UIDs to be stable and thus EXPUNGE cannot be done during the request).
func (iu *imapUser) pauseEventLoop() {
iu.eventLoopPausingLocker.Lock()
defer iu.eventLoopPausingLocker.Unlock()
iu.eventLoopPausingCounter++
iu.storeUser.PauseEventLoop(true)
}
// unpauseEventLoop unpauses event loop but only if no other request is not
// performing action forbidding event loop to run (see pauseEventLoop).
func (iu *imapUser) unpauseEventLoop() {
iu.eventLoopPausingLocker.Lock()
defer iu.eventLoopPausingLocker.Unlock()
if iu.eventLoopPausingCounter > 0 {
iu.eventLoopPausingCounter--
}
if iu.eventLoopPausingCounter == 0 {
iu.storeUser.PauseEventLoop(false)
}
}
func (iu *imapUser) isSubscribed(labelID string) bool {
subscriptionExceptions := iu.backend.getCacheList(iu.storeUser.UserID(), SubscriptionException)
exceptions := strings.Split(subscriptionExceptions, ";")