Por solicitação, aqui está um resumo do nosso problema e como o resolvemos:
Em nosso sistema, criamos uma rotina personalizada de bloqueio de documentos (usando redis-lock), em que o seguinte aconteceu nesta ordem precisa (incorreta):
ORDEM DE OPERAÇÕES INCORRETA:
- Solicitação do cliente recebida
- Documento bloqueado
- Documento recuperado
- Documento editado
- Documento desbloqueado
- Solicitação do cliente resolvida
- Documento salvo
Depois de vê-lo escrito, o problema é óbvio:estávamos salvando nossos documentos fora do nosso bloqueio de documentos.
Vamos supor que #6 leva 100ms em nosso sistema. Essa é uma janela de 100ms em que, se qualquer outra solicitação pegar o mesmo documento, teremos um conflito de salvamento (o erro intitulado nesta pergunta é basicamente um IMHO de conflito de salvamento).
Em outras palavras/exemplo:em nosso sistema, a Solicitação A pegou a Versão 1 do Documento X, editou-a e desbloqueou-a, mas antes da Solicitação A salvar o Documento, a Solicitação B pegou o Documento X e o incrementou para a Versão 2 (leia sobre Mongo versões para obter mais informações sobre isso). Então a Solicitação A resolve sua solicitação do Cliente e vai salvar o Documento X, mas está tentando salvar a Versão 1, e agora vê que tem a Versão 2, e daí o erro acima.
Então a correção é fácil. Salve seus documentos dentro de seu cadeado. (No exemplo acima, mova #7 para antes de #5. Veja abaixo.)
ORDEM DE OPERAÇÕES CORRETA/FIXA
- Solicitação do cliente recebida
- Documento bloqueado
- Documento recuperado
- Documento editado
- Documento salvo
- Documento desbloqueado
- Solicitação do cliente resolvida
(Você pode argumentar que #6 e #7 devem ser trocados, mas isso está fora do escopo do Mongo/Mongoose/esta questão.)
Vou deixar essa pergunta sem resposta por um tempo e ver se alguém pode lançar alguma luz sobre uma maneira melhor de isolar o código relevante e solucionar esse problema. No nosso caso, este foi um problema muito sistêmico e MUITO desafiador para solucionar o nosso nível de habilidade na época.