با این حال، جالب است که چگونه ما مدیریت پیام و ذخیرهسازی شناسه پیام پردازش شده را پیادهسازی میکنیم.
شما میتوانید مصرفکننده idempotent را به عنوان یک دکوراتور (decorator) 🎨 در اطراف یک message handler معمولی پیادهسازی کنید.
من دو پیادهسازی را به شما نشان خواهم داد:
🔹 مصرفکننده idempotent تنبل (Lazy)
🔹 مصرفکننده idempotent مشتاق (Eager)
مصرفکننده Idempotent تنبل (Lazy) 😴
مصرفکننده idempotent تنبل با جریانی که در الگوریتم بالا نشان داده شد، مطابقت دارد.
"تنبل" به نحوه ذخیرهسازی شناسه پیام برای علامتگذاری آن به عنوان پردازش شده، اشاره دارد.
در مسیر خوشحال (happy path) ✅، ما پیام را مدیریت کرده و شناسه پیام را ذخیره میکنیم.
اگر message handler یک استثنا پرتاب کند 💥، ما هرگز شناسه پیام را ذخیره نمیکنیم و مصرفکننده میتواند دوباره اجرا شود.
در اینجا شکل پیادهسازی آمده است: 👇
public class IdempotentConsumer<T> : IHandleMessages<T>
where T : IMessage
{
private readonly IMessageRepository _messageRepository;
private readonly IHandleMessages<T> _decorated;
public IdempotentConsumer(
IMessageRepository messageRepository,
IHandleMessages<T> decorated)
{
_messageRepository = messageRepository;
_decorated = decorated;
}
public async Task Handle(T message)
{
if (_messageRepository.IsProcessed(message.Id))
{
return;
}
await _decorated.Handle(message);
_messageRepository.Store(message.Id);
}
}