Давайте рассмотрим различные шаблоны доставки сообщений:
- Как минимум один раз - сообщение удаляется из источника после его доставки в цель.Одно и то же сообщение может быть отправлено несколько раз.
- Это то, что вы получили сейчас.
- Не более одного раза - сообщение удаляется из источника, прежде чем оно будет доставлено в цель.Данные могут быть потеряны.
- Скорее всего, не то, что вам нужно.
- Ровно один раз - сообщение будет удалено из источника одновременно с доставкой его адресату.
- Святой Грааль.Очень трудно достичь.
Хорошо, так что вы, по сути, хотите семантику Ровно .Этого можно достичь только при перемещении данных между очередями в одном и том же посреднике, между таблицами в базе данных или перемещением файла на локальный диск (или внутри одного и того же «ресурса»).
Когда выиметь несколько протоколов / ресурсов, это почти невозможно, или, по крайней мере, очень сложно.Есть несколько способов обеспечить точную однократную доставку с использованием транзакций «двухфазного принятия» с использованием распределенного координатора транзакций, такого как MSDTC в Windows или Atomikos в Java (среди прочих).Они будут поддерживать только транзакционные ресурсы, такие как очереди и базы данных, а не файловые системы, такие как SMB.
Другой способ - использовать sagas-pattern .Этот паттерн может быть немного излишним в этом случае.
Так что же делать?Хорошо - я могу придумать хотя бы один способ:
Идемпотентный потребительский паттерн .Это заставляет Camel хранить копии каждого сообщения (или, по крайней мере, ключа), такого как имя файла) в памяти, чтобы гарантировать, что ни одно сообщение не будет доставлено более одного раза.
// Something like this
from("smb://someplace?&idempotentKey=${file:name}&idempotent=true")
. // Whatnot
.to("activemq:queue:foobar");
Обратите внимание, что вы можете настроить идемпотентное хранилище для хранения записей в базе данных, на диске или в нескольких других местах, если вы хотите что-то более постоянное (но также и более сложное).