Digamos que você tenha essa tarefa em um aplicativo composto de duas partes:
1) Entrega de um arquivo para um sistema externo (não em seu controle)
2) Uma transação de banco de dados em nosso sistema, com informações sobre a referida entrega (o que foi enviado, quando e por quem)
Se qualquer uma dessas duas partes falhar, o estado do nosso sistema será inconsistente. Se um arquivo foi enviado e o banco de dados não tiver informações sobre ele, é um erro. Da mesma forma, se a transferência de arquivos falhou, mas as informações no banco de dados sugerem o contrário, isso também é um erro.
Como você abordaria essa tarefa para garantir que o banco de dados permanecesse em um estado consistente após cada vez que a tarefa fosse tentada?
Sou inexperiente em lidar com problemas como esse de uma maneira correta - sempre posso usar a abordagem ingênua e fingir que escrever no banco de dados nunca falhará. :-) Eu desejo fazer melhor que isso, no entanto.
As duas variações básicas que vejo aqui ambas deixam algo a desejar (pseudocódigo):
A:
try:
commitTransaction()
deliverFile()
catch TransactionError:
// No problem, delivery was never attempted.
catch DeliveryError:
// The system will now say that it was delivered,
// even though it wasn't.
B:
try:
deliverFile()
commitTransaction()
catch TransactionError:
// The system will now say nothing was delivered,
// even though it was.
catch DeliveryError:
// Easy enough to handle:
rollbackTransaction()
Tenho certeza de que há uma solução aceitável para isso e que simplesmente não consigo identificar?