quickfix icon indicating copy to clipboard operation
quickfix copied to clipboard

Persist can cause store to get into inconsistent state

Open imirkin opened this issue 4 years ago • 1 comments

Let's say that one is using the sql store. Persist looks like this:

func (s *session) persist(seqNum int, msgBytes []byte) error {
        if !s.DisableMessagePersist {
                if err := s.store.SaveMessage(seqNum, msgBytes); err != nil {
                        return err
                }
        }

        return s.store.IncrNextSenderMsgSeqNum()
}

So it will save the message to the messages table, and after that, update the outgoing seqnum in the sessions table.

However if the process is terminated in the middle (or there's a database error), you can end up with the message in the messages table, but the outgoing seqnum will still be the old one in the sessions table. Ideally there'd be some transactionality here, but the interfaces don't have anything like that.

This causes problems when the process is restarted and tries to send a message. It will insert another message into the messages table, which will fail due to a primary key constraint.

I believe a reasonable solution would be to flip those two around. In the failure case outlined, you'll just have burned a seqnum, which seems like a reasonable thing to do in such an exceptional situation.

imirkin avatar Jul 05 '21 04:07 imirkin

Sure, if you're comfortable tackling this, feel free. Adding a test that fails would be a good start as well.

ackleymi avatar Jul 09 '21 00:07 ackleymi