It's possible (but very rare, I don't think proton still allows it)
for an address to have no keys. If we try to load the address keyring
for such an address, this change logs a warning that no decryption
entities were found in the unlocked keyring.
It bumps liteapi to a version that does not return an error when no
keys could be unlocked.
This change implements safe.Mutex and safe.RWMutex, which wrap the
sync.Mutex and sync.RWMutex types and are assigned a globally unique
integer ID. The safe.Lock and safe.RLock methods sort the mutexes
by this integer ID before locking to ensure that locks for a given
set of mutexes are always performed in the same order, avoiding
deadlocks.
Labels can be held locally and updated in memory. This greatly improves
the responsiveness of IMAP mailbox operations as we don't need to fetch
all a user's labels to find the parent whenever a mailbox is moved.
Although most race conditions have been eliminated, there are some known
ones, particularly in the go-imap client used by the integration tests,
which is out of our control.
Over time we will hopefully eliminate these but for now, let's not rely
on the race checks consistently passing.
When changing address mode, we would close all a user's update channels
and create them from scratch. This involved setting user.updateCh to a
new value. However, it was possible for other goroutines to read from
user.updateCh during this time. I replaced it with a call to
user.updateCh.Clear(), which is threadsafe.
We were closing the event QueuedChannel objects in the wrong place;
they should have been closed on test teardown, not on stopBridge
(which was just a test action and wasn't always called).
In order to make the events more scalable, i replace all the
QueuedChannel objects with a single event collector, which would
create QueuedChannels on demand when it receives an event of a new type.