# ADR-R2: جایگزینی Redis با قفل/شمارنده مبتنی بر MariaDB

- **تاریخ:** 2026-09-07
- **وضعیت:** پیشنهادی — نیازمند تأیید مالک پروژه (حسن)
- **ارتباط:** جایگزین بخشی از ADR-001؛ مرتبط با ADR-004 (Idempotency)

## زمینه (Context)
سرور Redis روی هاست اشتراکی/ابری سون‌هاست ارائه نمی‌شود (تأیید پشتیبانی).
کد مرجع NestJS از RedisService برای چهار منظور استفاده می‌کند:
1. قفل توزیع‌شده (Idempotency و تسویه Escrow)
2. شمارنده اتمیک سقف‌دار (Rate-limit پیامک/OTP — فصل ۶.۳)
3. کش عمومی (feature flags، مجوزهای RBAC، نتایج rules engine)
4. ذخیره OTP با TTL (`otp:{phone}`) و توکن‌های refresh

## گزینه‌های بررسی‌شده (Options)
1. **Redis خارج از هاست** — رد شد (همان دلیل ADR-R1).
2. **فایل‌های lock روی دیسک** — ناسازگار با چند worker؛ پاک‌سازی پس از crash مسئله‌ساز.
3. **MariaDB به‌عنوان KV: جدول‌ها + `GET_LOCK()` + unique index + TTL نرم (expires_at)**

## تصمیم (Decision)
گزینه ۳، با نگاشت هر الگوی Redis به معادل MariaDB:

| الگوی Redis | معادل MariaDB |
|---|---|
| `SET NX EX` (قفل) | `GET_LOCK(key, timeout)` + `RELEASE_LOCK()` (session-scoped، خود-release در قطع اتصال) |
| `INCR + EXPIRE` (شمارنده) | جدول `core_rate_limits (key, count, expires_at)` با `INSERT ... ON DUPLICATE KEY UPDATE count = count + 1` + پاک‌سازی منقضی‌ها |
| `GET/SET` با TTL | جدول `core_kv_cache (key, value JSON, expires_at)` — lazy expiry |
| OTP با TTL | جدول `auth_otp_codes` با `expires_at` و سقف تلاش |
| refresh token | جدول `auth_refresh_tokens` (opaque, hashed) |

Singleton اپ (Laravel روی Apache هاست) است؛ `GET_LOCK` ماریا‌دی‌بی برای چند worker/process امن است.
Page cache و config cache لاراول نیز روی درایور `database` می‌روند.

## پیامدها (Consequences)
- **مثبت:** صفر وابستگی خارجی؛ رفتار اتمیک تضمین‌شده در سطح DB؛ تست‌پذیر با transactions.
- **منفی:** کمی کندتر از Redis (round-trip دیسک) — برای ترافیک فاز ۱ قابل قبول؛
  جدول rate-limit باید با یک job Cron هر دقیقه از ردیف‌های منقضی پاک شود (VACUUM سبک).
- **مهاجرت آینده:** اگر روزی VPS با Redis گرفتیم، فقط پیاده‌سازی `CacheStore`/`LockManager`
  عوض می‌شود؛ رابط سرویس ثابت می‌ماند (همان الگوی wrapper نازک نسخه NestJS).

## ارجاعات
- نسخه مرجع: `iraniraqgate/apps/api/src/shared/redis/redis.service.ts` (رابط ۱۱ مصرف‌کننده)
- فصل ۶.۳ (OTP/Rate-limit)، ADR-004 (Idempotency)
