Читаем GC-лог без страха
Сборка мусора — не магия. Практическая карта того, что говорит JVM, и какие паузы действительно важны.
Бэкенд — это в основном про эффекты, а не про сообщения. Запрос может прийти дважды; то, что он запускает, дважды произойти не должно. Чем раньше закладываешь это в дизайн, тем спокойнее дежурства.
Приём — стабильный ключ, по которому система делает дедупликацию, плюс надёжное место, где она помнит уже обработанные ключи — в идеале в той же транзакции, что делает работу.
Ниже — форма, к которой я тяготею. Если вставка конфликтует, работа уже сделана — подтверждаем и идём дальше. Без распределённых локов и второй системы для синхронизации. Скучно, надёжно, предсказуемо.
1 void handle(Message m) {2 // the message may arrive twice; the effect must not3 String key = m.dedupeKey();4 tx.run(() -> {5 if (seen.contains(key)) return; // already done — ack6 seen.mark(key);7 work(m);8 });9 }
Вот и вся идея. Сложным было не «доставить», а решить, что значит «та же работа», и записать это куда-то надёжно.