TGViewer
C# Geeks (.NET) C# Geeks (.NET) @csharpgeeks · 550 subscribers
Post #461 144
⚙️ Publisher-Side Idempotency (بگذارید Broker آن را مدیریت کند)

بسیاری از message brokerها از قبل از طریق قابلیت message deduplication، از انتشار idempotent پشتیبانی می‌کنند؛ البته اگر در پیام خود یک شناسه‌ی یکتا (unique message ID) قرار دهید.

به‌عنوان مثال، Azure Service Bus می‌تواند پیام‌های تکراری را تشخیص داده و انتشار مجدد پیام‌هایی با MessageId یکسان را در بازه‌ی زمانی مشخص‌شده نادیده بگیرد.Amazon SQS و سایر brokerها نیز تضمین‌های مشابهی ارائه می‌دهند. 💪

✅ شما نیازی ندارید این منطق را دوباره در برنامه‌ی خود پیاده‌سازی کنید.
نکته‌ی کلیدی این است که برای هر پیام، یک شناسه‌ی پایدار (stable identifier) اختصاص دهید که به‌طور یکتا رویداد منطقی مورد نظر را نمایش دهد.

به‌عنوان مثال، هنگام انتشار یک event از نوع NoteCreated:
var message = new NoteCreated(note.Id, note.Title, note.Content)
{
MessageId = Guid.NewGuid() // یا می‌توانید از note.Id استفاده کنید
};

await publisher.PublishAsync(message);


اگر شبکه پس از ارسال پیام قطع شود 🌐، ممکن است برنامه‌ی شما ارسال را مجدداً تلاش کند (retry).
اما زمانی که broker همان MessageId را مشاهده کند، متوجه می‌شود که این پیام تکراری است و آن را به‌صورت ایمن نادیده می‌گیرد. ✅

به این ترتیب، شما deduplication را بدون نیاز به جداول ردیابی (tracking tables) یا state اضافی در سرویس خود به‌دست می‌آورید.

این نوع idempotency در سطح broker، بخش بزرگی از مشکلات سمت producer را حل می‌کند مثل:

• retryهای شبکه 🔁
• خطاهای موقتی ⚠️
• انتشارهای تکراری 🌀

اما چیزی که این مکانیسم پوشش نمی‌دهد، retryهای سمت consumer است یعنی زمانی که پیام‌ها مجدداً تحویل داده می‌شوند یا سرویس شما هنگام پردازش دچار crash می‌شود 💥.

اینجاست که الگوی Idempotent Consumer وارد عمل می‌شود. 🎯

🧠 Implementing an Idempotent Consumer in .NET

در اینجا یک نمونه از Idempotent Consumer برای eventی از نوع NoteCreated آورده شده است:
internal sealed class NoteCreatedConsumer(
TagsDbContext dbContext,
HybridCache hybridCache,
ILogger<Program> logger) : IConsumer<NoteCreated>
{
public async Task ConsumeAsync(ConsumeContext<NoteCreated> context)
{
// 1. بررسی اینکه آیا این پیام قبلاً توسط این consumer پردازش شده است
if (await dbContext.MessageConsumers.AnyAsync(c =>
c.MessageId == context.MessageId &&
c.ConsumerName == nameof(NoteCreatedConsumer)))
{
return;
}

var request = new AnalyzeNoteRequest(
context.Message.NoteId,
context.Message.Title,
context.Message.Content);

try
{
using var transaction = await dbContext.Database.BeginTransactionAsync();

// 2. پردازش قطعی (Deterministic): استخراج تگ‌ها از محتوای یادداشت
var tags = AnalyzeContentForTags(request.Title, request.Content);

// 3. ذخیره‌سازی تگ‌ها در پایگاه داده
var tagEntities = tags.Select(ProjectToTagEntity(request.NoteId)).ToList();
dbContext.Tags.AddRange(tagEntities);

// 4. ثبت اینکه این پیام پردازش شده است
dbContext.MessageConsumers.Add(new MessageConsumer
{
MessageId = context.MessageId,
ConsumerName = nameof(NoteCreatedConsumer),
ConsumedAtUtc = DateTime.UtcNow
});

await dbContext.SaveChangesAsync();
await transaction.CommitAsync();

// 5. به‌روزرسانی Cache
await CacheNoteTags(request, tags);
}
catch (Exception ex)
{
logger.LogError(ex, "Error analyzing note {NoteId}", request.NoteId);
throw;
}
}
}

این یک نمونه‌ی متداول از Idempotent Consumer است که شامل چند نکته‌ی کلیدی است 🧩
More from @csharpgeeks
  1. Sep 22, 2026یه مدتی قراره از دنیای NET. فاصله بگیرم، چون وقتشه برم سربازی. راستش نمیدونم این مدت رو چج…
  2. Sep 20, 2026🔥 حالا مشکل اصلی: Alert Storm فرض کن Database از دسترس خارج شده. ۱۰۰ Pod داری. هر Pod می‌…
  3. Sep 20, 2026🚨 طراحی سیستم Monitoring و Alerting در یک سیستم بزرگ فرض کن ساعت ۳ صبح است. سیستم شما با…
  4. Sep 19, 2026#Engineering_Leadership تصمیم نگرفتن هم یک تصمیم است یه چیز عجیب توی تیم‌های مهندسی: گاهی…
  5. Sep 19, 2026☑ چک‌لیست آماده‌سازی تیم، فرایندها و زیرساخت برای توسعه با AI توجه: هیچ چک‌لیستی جهان‌شمول…
  6. Sep 19, 2026📌پایان یک انتظار طولانی: اعتبارسنجی ناهمگام (Async Validation) در NET 11.
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →