# Idempotency

> أرسل Idempotency-Key مع طلبات POST حتى لا تؤدي إعادة إرسال الطلب إلى تنفيذ الفحص أو احتساب رسمه مرتين. شرح السلوك والاستجابات المُعادة والتعارضات.

المصدر: https://fileverity.com/ar/docs/idempotency

قد يتركك تعطّل الشبكة غير متأكد مما إذا كان طلب POST قد وصل. وإذا أعدت إرساله ببساطة، فقد يُنفَّذ الفحص ويُحتسب سعره مرتين. أرسل الترويسة `Idempotency-Key` فيعيد الطلب المُعاد الاستجابة الأولى بدلًا من تنفيذه من جديد.

## استخدام الترويسة

**طلب مع Idempotency-Key: cURL**

```bash
curl https://api.fileverity.com/v1/analyses \
  -H "Authorization: Bearer $FILEVERITY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 0e5f6a64-52c2-4b36-9d0d-6f3d2f4c9a10" \
  -d '{"model": "fvimg-2", "file": "file_8Hk2pQ4vN9sL1xR7cW3mY6zB"}'
```

**طلب مع Idempotency-Key: JavaScript**

```javascript
async function createAnalysis(body) {
  const key = crypto.randomUUID();
  let lastError;
  for (let attempt = 0; attempt < 3; attempt++) {
    try {
      return await fetch("https://api.fileverity.com/v1/analyses", {
        method: "POST",
        headers: { Authorization: "Bearer " + process.env.FILEVERITY_API_KEY, "Content-Type": "application/json", "Idempotency-Key": key },
        body: JSON.stringify(body),
      });
    } catch (error) {
      lastError = error;
    }
  }
  throw lastError;
}
```

**طلب مع Idempotency-Key: Python**

```python
import uuid

def create_analysis(body):
    key = str(uuid.uuid4())
    last_error = None
    for attempt in range(3):
        try:
            return requests.post("https://api.fileverity.com/v1/analyses", headers={**headers, "Idempotency-Key": key}, json=body, timeout=90)
        except requests.ConnectionError as error:
            last_error = error
    raise last_error
```

- أرسل أي سلسلة نصية فريدة طولها من 1 إلى 255 حرفًا. ويُعد معرّف UUID عشوائي خيارًا جيدًا. استخدم مفتاحًا جديدًا لكل طلب مختلف، ولا تعِد استخدام المفتاح نفسه إلا لإعادة محاولة الطلب نفسه.
- يعمل مع كل نقطة نهاية من نوع POST: `/text/detections` و`/files` و`/analyses` و`/analyses/{id}/cancel`.
- يرتبط كل مفتاح بمساحة عملك وبالوضع (حقيقي أو اختبار) وبنقطة النهاية، ويُحفظ 24 ساعة. ولا يحدث تعارض إذا استُخدم المفتاح نفسه مع مفتاح حقيقي ومفتاح اختبار.

## ما تحصل عليه

| الحالة | النتيجة |
| --- | --- |
| أول طلب بمفتاح معيّن | يُعالَج بصورة طبيعية. وتُحفظ الاستجابات الناجحة (رمز الحالة أقل من 400). |
| المفتاح نفسه ومحتوى الطلب نفسه خلال 24 ساعة | الاستجابة المحفوظة برمز الحالة نفسه، مع الترويسة `idempotent-replayed: true`. لا يُنفَّذ شيء ولا يُحتسب شيء مرة أخرى. |
| المفتاح نفسه مع محتوى طلب مختلف | `409` `idempotency_mismatch`. |
| المفتاح نفسه بينما لا يزال الطلب الأول قيد التنفيذ | `409` `idempotency_in_progress`. أعد المحاولة بعد قليل. |
| المفتاح نفسه بعد استجابة خطأ | يُحرَّر المفتاح. لا تُحفظ استجابة الخطأ، لذا تؤدي إعادة المحاولة إلى تنفيذ الطلب من جديد. |

تحمل الاستجابة المُعادة قيمة `x-request-id` الخاصة بالطلب الجديد، لا بالطلب الأصلي. وتُقارَن عمليات الرفع بصيغة multipart بحسب حقول النموذج ومحتوى الملف.

> **ملاحظة.** تمنع Idempotency تكرار العمل، لكنها لا تجعل الطلب الفاشل ينجح: بعد `service_unavailable` أو `internal_error`، انتظر عدد الثواني الوارد في `retry-after` إن كانت الاستجابة تحمل هذه الترويسة، ثم أعد المحاولة بالمفتاح نفسه.

راجع أيضًا [الأخطاء](https://fileverity.com/ar/docs/errors.md) و[حدود المعدّل والترويسات](https://fileverity.com/ar/docs/rate-limits.md).

