On Wed, Jul 27, 2005 at 11:40:07AM -0400, Geo Carncross wrote:

> Because that's not what IMAP flags are. They're individual
> annotations to a message, not a single annotation - as all the flags
> and keywords combined.

How does dbmail store flags?  If it stored each flag as a separate
entry in a relational table, you're covered.  If not, you're not.

> Clearly if a client said "STORE FLAGS (\Answered)" "STORE FLAGS
> (+FOOBaz)" they wouldn't care, but if they said:
> 
> STORE +FLAGS (\Answered)
> STORE +FLAGS (+FOOBaz)
> 
> they really mean for both of those flags to be stored.

Not necessarily.  You're assuming that the protocol's semantics are
reflecting what the user means to do, which is not necessarily the
case in multimaster (especially since the RFC says it assumes a single
master!)

In particular, say you have the following:

  Servers A and B have an email, UID 9, which has no flags set.

  Servers A and B lose sync.

  User connects to A, reads mail, decides to set flag +FOOBaz.  MUA
    chooses to implement this as STORE +FLAGS (+FOOBaz)

  User disconnects

  User connects to B, reads mail, notices that flag +FOOBaz WAS NOT
    SET, decides that's OK and that he just wants \Answered set.  MUA
    chooses to implement this as STORE +FLAGS (\Answered).  Note that
    if the user had wanted +FOOBaz as well, he'd have clicked that,
    too, and the MUA would have run STORE +FLAGS (\Answered +FOOBaz)

  User calls helpdesk to complain that flag mysteriously disappeared.
    They tell him to try setting it again.  He says he doesn't want it
    any longer, he was just calling to find out what happened to it.
    They say they're having some weird mail server problems, but he
    should still be able to read his email.

  Servers A and B regain sync, replicate, and merge flags.

  User connects to B again.  Now +FOOBaz and \Answered are set.

  User calls helpdesk again because the flag has mysteriously
    reappeared.  Helpdesk throws up hands in frustration.

But again -- if you choose to implement flags relationally, using a
flag per row, this kind of problem should be resolved the way you
expect.  When A interprets STORE +FLAGS (+FOOBaz), it runs something
like INSERT INTO flag_table values (9, "+FOOBaz").  When B interprets
STORE +FLAGS (\Answered), it runs something like INSERT INTO
flag_table values (9, "\Answered).  When replication occurs, there are
two entries in flag_table for UID 9, one for "+FOOBaz", one for
"\Answered".  This is what you expect, right?

The semantics of flags in a multimaster world are subtle.  What does
the user expect when the client does a set rather than an add,
ie. "STORE FLAGS (+FOOBaz)" in one session to one server, and "STORE
FLAGS (\Answered)" in another?  Ie. if there are no flags set to begin
with, does "set" reflect the user's preference, or does it reflect the
client's belief that there are no other flags set, so setting and
adding are equivalent ops?

IMHO, the semantics here are non-trivial.

> Consider an IMAP agent that periodically marks messages with the
> "Junk" keyword. Suddenly those flags disappear- but the message is
> no longer \Recent so that clients remove the junk-status.

> If someone leaves their Thunderbird all day, but periodically opens
> with Eudora, they've lost their junk-scanning abilities.

I'm not sure I follow this as a problem.  If the user has two
different clients running, even to the same server without any kind of
server clustering, each session is guaranteed to see different
messages as \Recent per the RFC, so the two sessions should interfere
with each other.  \Recent is a session flag, so it shouldn't be stored
in the DB to be persistent across sessions, and shouldn't cause
(additional) problems in a multimaster world.  The client MUST NOT be
able to set or unset \Recent explicitly with any IMAP ops per the RFC.

That said, if you are storing \Recent persistently, that's OK so long
as you're using a different row for each flag.  Ie.:

  Multimaster servers A and B are out-of-sync, but they each have an
    email, UID 9, with \Recent set.

  client 1 on server A sets Junk and implicitly unsets \Recent by
    logging out

  A runs: insert into flag_table values (9, "Junk");

  A runs: delete from flag_table where uid=9 and flag="\Recent"

  Client 2 on server B implicitly unsets \Recent by logging out

  B runs: delete from flag_table where uid=9 and flag="\Recent"

  A and B sync.  replication catches up.  End state has UID 9 with
    flag Junk and no flag "\Recent", as expected.

Again, the question is, how does dbmail store flags?

- Morty

Reply via email to