# Idempotency

> Gửi Idempotency-Key trong các yêu cầu POST để một yêu cầu được thử lại không bao giờ chạy hoặc tính phí một lượt kiểm tra hai lần. Cách hoạt động, phản hồi được phát lại và xung đột.

Nguồn: https://fileverity.com/vi/docs/idempotency

Lỗi mạng có thể khiến bạn không biết một yêu cầu POST đã đến nơi hay chưa. Nếu chỉ gửi lại, một lượt kiểm tra có thể chạy và bị tính phí hai lần. Hãy gửi header `Idempotency-Key`, khi đó lần gửi lại sẽ trả về phản hồi đầu tiên.

## Cách dùng header

**Yêu cầu idempotent: 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"}'
```

**Yêu cầu idempotent: 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;
}
```

**Yêu cầu idempotent: 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
```

- Gửi một chuỗi duy nhất bất kỳ dài từ 1 đến 255 ký tự. UUID ngẫu nhiên là một lựa chọn tốt. Dùng khóa mới cho mỗi yêu cầu khác nhau, và chỉ dùng lại cùng một khóa để thử lại chính yêu cầu đó.
- Header này áp dụng cho mọi endpoint POST: `/text/detections`, `/files`, `/analyses` và `/analyses/{id}/cancel`.
- Mỗi khóa chỉ có hiệu lực trong phạm vi không gian làm việc, chế độ (thật hoặc thử nghiệm) và endpoint của bạn, và được lưu trong 24 giờ. Cùng một Idempotency-Key dùng với khóa thật và với khóa thử nghiệm sẽ không xung đột.

## Bạn nhận lại được gì

| Tình huống | Kết quả |
| --- | --- |
| Yêu cầu đầu tiên với một khóa | Được xử lý bình thường. Các phản hồi thành công (mã trạng thái dưới 400) được lưu lại. |
| Cùng khóa và cùng nội dung yêu cầu trong vòng 24 giờ | Phản hồi đã lưu với cùng mã trạng thái, kèm header `idempotent-replayed: true`. Không có gì được chạy hoặc tính phí lại. |
| Cùng khóa, nội dung yêu cầu khác | `409` `idempotency_mismatch`. |
| Cùng khóa trong khi yêu cầu đầu tiên vẫn đang chạy | `409` `idempotency_in_progress`. Hãy thử lại sau giây lát. |
| Cùng khóa sau một phản hồi lỗi | Khóa được giải phóng. Phản hồi lỗi không được lưu, nên khi thử lại, yêu cầu sẽ được chạy lại. |

Phản hồi được phát lại giữ `x-request-id` của yêu cầu mới, không phải của yêu cầu gốc. Với tải lên dạng multipart, hệ thống so sánh các trường biểu mẫu và nội dung tệp.

> **Lưu ý.** Idempotency loại bỏ công việc trùng lặp. Nó không làm một yêu cầu thất bại trở nên thành công: sau `service_unavailable` hoặc `internal_error`, hãy chờ số giây trong `retry-after` nếu phản hồi có header đó, rồi thử lại với cùng khóa.

Xem thêm [Lỗi](https://fileverity.com/vi/docs/errors.md) và [Giới hạn tốc độ và header](https://fileverity.com/vi/docs/rate-limits.md).

