پرش به محتویات

پردازش غیرهمزمان و اعلان

نسخه اول از صف پایدار PostgreSQL و Worker همان Codebase استفاده می‌کند. Redis، RabbitMQ و Kafka تا زمانی که Metric نیاز عملیاتی آن‌ها را اثبات نکرده است اضافه نمی‌شوند.

کاربرد Job

کار باید غیرهمزمان شود اگر یکی از شرایط زیر برقرار است:

  • به SMS، Push، Webhook، Object Storage یا Provider بیرونی وابسته است.
  • ممکن است از بودجه پاسخ API عبور کند.
  • Retry، Schedule، Batch یا Rate Limit Provider لازم دارد.
  • نتیجه آن پس از Commit کسب‌وکار قابل انجام است.

Validation، Authorization و Invariant اصلی داخل Request و پیش از ثبت Job انجام می‌شوند. Job نباید خطای قابل پیش‌بینی کاربر را دیرهنگام کشف کند.

Transactional Outbox

تغییر داده دامنه و ثبت Event Outbox در یک Transaction انجام می‌شود. Worker پس از Commit، Event را به Job یا Delivery تبدیل می‌کند. Dual-write مستقیم «Database سپس Provider» یا برعکس ممنوع است.

هر Event شامل شناسه یکتا، نوع نسخه‌دار، Aggregate، Tenant، زمان وقوع، Correlation ID و Payload حداقلی است. PII و Snapshot بزرگ بدون نیاز وارد Event نمی‌شود.

مدل Job

فیلد هدف
id UUIDv7 یکتا
type و version Handler و قرارداد Payload
tenant_id Scope و Fairness
idempotency_key جلوگیری از اجرای اثر تکراری
payload داده حداقلی JSONB یا Reference پایدار
status pending، running، succeeded، retryable، dead
attempts و max_attempts سیاست Retry
available_at Schedule و Backoff
locked_by و locked_until Lease و بازیابی Worker مرده
last_error_code خطای Redacted و قابل گروه‌بندی

Worker با FOR UPDATE SKIP LOCKED یک Batch محدود Claim می‌کند و Lock را سریع آزاد می‌کند. Lease منقضی‌شده قابل بازیابی است و Heartbeat فقط برای کار طولانی مجاز است.

Idempotency و Delivery

  • Semantics صف حداقل یک‌بار است؛ Handler باید Idempotent باشد.
  • اثر نهایی با Unique Constraint، Inbox Table Provider یا State Check دامنه‌ای محافظت می‌شود.
  • موفقیت فقط پس از تایید نتیجه پایدار ثبت می‌شود.
  • Timeout مبهم Provider پیش از Retry با Query وضعیت یا Idempotency Provider Reconcile می‌شود.
  • ترتیب فقط در Aggregateهایی که نیاز واقعی دارند حفظ می‌شود؛ Sequence سراسری هزینه غیرضروری دارد.
  • Event قدیمی با Upcaster یا Handler نسخه خودش خوانده می‌شود و Payload Merge‌شده ویرایش نمی‌شود.

Retry و Dead Letter

  • خطا به Permanent، Retryable و Unknown طبقه‌بندی می‌شود.
  • Retry با Exponential Backoff، Full Jitter، سقف زمانی و حداکثر تلاش محدود اجرا می‌شود.
  • 429 و Retry-After Provider رعایت می‌شوند؛ 4xx قطعی بدون Retry به Dead Letter یا نتیجه کسب‌وکار می‌رود.
  • پس از پایان تلاش‌ها Job به dead می‌رود، Alert و ابزار Replay کنترل‌شده ایجاد می‌شود.
  • Replay نیازمند Permission عملیاتی، دلیل، Audit و Idempotency است؛ ویرایش Payload تاریخی ممنوع است.
  • Poison Job نباید Queue یک Tenant یا Type دیگر را متوقف کند.

Fairness و فشار معکوس

  • Concurrency برای هر Job Type و Provider محدود است.
  • Tenant پرمصرف نباید تمام Workerها را اشغال کند؛ Claim و Rate Limit باید Fairness حداقلی داشته باشد.
  • Queue Depth، Age قدیمی‌ترین Job، Throughput، Retry Rate، Dead Count و زمان Handler Metric دارند.
  • در Backlog بالا، Job کم‌اولویت دیرتر اجرا و مسیرهای حیاتی مانند OTP و مالی ظرفیت رزروشده دارند.
  • API در Overload به‌جای پذیرش بی‌نهایت، Backpressure و 503 یا 429 کنترل‌شده می‌دهد.

مدل اعلان

Inbox داخل برنامه منبع حقیقت اعلان است. هر رویداد بر اساس Policy به یک یا چند کانال تبدیل می‌شود:

کانال کاربرد
In-app Inbox همه اعلان‌های قابل پیگیری و تاریخچه‌دار
SSE به‌روزرسانی Foreground وب
Push آگاه‌سازی Background موبایل
SMS OTP و رویدادهای بحرانی، رسمی یا مالی تصویب‌شده
  • Preference کاربر، Permission، عضویت فعال، Quiet Hours و حساسیت محتوا پیش از Delivery بررسی می‌شوند.
  • Push Payload شامل Secret یا متن حساس کامل نیست و Client پس از بازشدن Detail را از REST می‌گیرد.
  • Token دستگاه Lifecycle دارد؛ Token نامعتبر Provider غیرفعال و Cleanup می‌شود.
  • Deduplication بر اساس Recipient، Event و Channel انجام می‌شود.
  • Delivery و Read State جدا هستند؛ تحویل Push به معنی خواندن پیام نیست.
  • Template نسخه‌دار، قابل Preview و دارای Fallback فارسی است.

Ticket

Ticket یک Workflow دامنه‌ای است، نه Chat. Feature آن باید ایجاد، دسته‌بندی، Assignment، SLA، پاسخ، یادداشت داخلی، Attachment، تغییر Status، تصمیم، Resolution و Audit را نگهداری کند. پیام داخلی فقط برای نقش مجاز قابل مشاهده است و هر Transition با استاندارد Workflow سازگار می‌ماند.

معیار پذیرش

  • Crash Worker بین اثر بیرونی و ثبت Success باعث اثر تکراری غیرمجاز نمی‌شود.
  • Job منقضی یا Poison به‌صورت قابل مشاهده Dead Letter می‌شود.
  • Queue OTP زیر بار Jobهای کم‌اولویت همچنان ظرفیت هدف دارد.
  • از دست رفتن Push یا SSE با Sync از Inbox جبران می‌شود.
  • Replay عملیاتی Permission، Audit و نتیجه قابل ردیابی دارد.

منابع رسمی