Вы просматриваете 2 разные клиентские библиотеки:
- объект objectify, который включает автоматические c повторов, настраиваемый
- файл простого хранилища данных, который не включая такие повторы, вам придется самим позаботиться о повторных попытках
Проблема перевода денег не обязательно не идемпотентна, в том смысле, что ее можно сделать идемпотентом с помощью транзакций. Ключ заключается в том, чтобы включить обе модификации учетной записи в одну и ту же транзакцию, как показано в примере клиента хранилища данных :
void transferFunds(Key fromKey, Key toKey, long amount) {
Transaction txn = datastore.newTransaction();
try {
List<Entity> entities = txn.fetch(fromKey, toKey);
Entity from = entities.get(0);
Entity updatedFrom =
Entity.newBuilder(from).set("balance", from.getLong("balance") - amount).build();
Entity to = entities.get(1);
Entity updatedTo = Entity.newBuilder(to).set("balance", to.getLong("balance") + amount)
.build();
txn.put(updatedFrom, updatedTo);
txn.commit();
} finally {
if (txn.isActive()) {
txn.rollback();
}
}
}
Таким образом, либо обновляются обе учетные записи, либо ни одна из них не является - если транзакция завершается неудачей, все изменения либо не фиксируются, либо откатываются.
FWIW, чтобы проверить мою (ndb
) логи повторных попыток транзакции c и идемпотентность I поместила транзакции (с соответствующими сообщениями отладки) в pu sh обработчики очереди задач и одновременно запускали несколько задач, вызывая конфликты. Журналов запросов и приложений было вполне достаточно для проверок.