# Ограничения скорости и параллелизм

Tripo API применяет ограничения скорости и параллелизма для обеспечения стабильности сервиса и справедливого использования.

## Ограничения ставок

Ограничения скорости ограничивают количество запросов API, которые вы можете сделать в пределах временного окна.

### Ограничительные правила

- Ограничения скорости рассчитываются на уровне **API Key**.
- Ограничения различаются в зависимости от конечной точки. Конечные точки генерации, такие как `/v3/generation/*`, имеют более низкие ограничения, а конечные точки запроса, такие как `/v3/tasks/*`, имеют более высокие ограничения.
- При превышении лимита API возвращает HTTP `429 Too Many Requests` с кодом ошибки `1007`.

### Заголовки ответов

Каждый ответ API включает заголовки ответа, связанные с ограничением скорости:

| Заголовок ответа | Описание |
| :-: | :-: |
| `X-RateLimit-Limit` | Максимальное количество запросов, разрешенное в текущем временном окне |
| `X-RateLimit-Remaining` | Количество оставшихся запросов, доступных в текущем временном окне |
| `X-RateLimit-Reset` | Временная метка Unix в секундах, когда окно ограничения скорости сбрасывается. |

### Реакция при ограничении скорости

```json
{
  "code": 1007,
  "message": "Rate limit exceeded, you've generated too many requests in a short amount of time",
  "suggestion": "Please wait for a while and try again"
}
```

---

## Ограничения параллелизма

Ограничения параллелизма ограничивают количество задач, которые могут выполняться **одновременно** под вашей учетной записью. Это отличается от ограничений скорости: ограничения скорости ограничивают частоту запросов, а ограничения параллелизма ограничивают параллельно выполняемые задачи.

### Как это работает

- Параллелизм рассчитывается на уровне **учетной записи** (не для API Key).
- Ограничения применяются **для каждой категории задач** — каждая категория имеет свой собственный независимый пул параллелизма.
- Когда параллелизм категории заполнен, при создании новой задачи для этой категории возвращается HTTP `429` с кодом ошибки `2000`.
- Задачи в других категориях **не затрагиваются** — вы по-прежнему можете создавать задачи в категориях, в которых есть свободные слоты.

### Пределы по умолчанию

Все пользователи начинают с параллелизма по умолчанию, равного **10** для каждой категории; в некоторых категориях установлены другие лимиты (см. таблицу ниже).

| Категория | Включенные типы задач | Параллелизм по умолчанию |
| :-: | :-: | :-: |
| 3D-поколение — серия H | преобразование текста в модель (H), преобразование изображения в модель (H), преобразование нескольких представлений в модель (H) | 10 |
| 3D-генерация — серия P | преобразование текста в модель (P), преобразование изображения в модель (P), преобразование нескольких представлений в модель (P) | 5 |
| Генерация изображений | преобразование текста в изображение, изображение в изображение, изображение в несколько изображений, редактирование нескольких изображений | 1 |
| Анимация | авто-риг, проверка рига, перенацеливание анимации | 10 |
| Обработка модели | текстура, преобразование формата, уточнение | 5 |
| Операции с сеткой | сегментация, завершение, ретопология | 10 |

> **Примечание.** Задачи одной категории используют общий пул параллелизма. Например, если у вас запущено 10 задач преобразования текста в модель серии H, вы не сможете запустить задачу преобразования изображения в модель серии H, пока одна из них не будет завершена. Однако вы по-прежнему можете запускать задачи P-серии или создания изображений.

### Реакция при превышении параллелизма

```json
{
  "code": 2000,
  "message": "You have exceeded the limit of generation",
  "suggestion": "Try again later. You can also check `Retry-After` header."
}
```

Ответ включает заголовок `Retry-After`, указывающий, сколько секунд нужно подождать перед повторной попыткой.

### Увеличение параллелизма

Чтобы запросить более высокие лимиты одновременности, свяжитесь с нашей командой через канал поддержки. Пользовательский параллелизм можно настроить для каждой категории в зависимости от ваших потребностей в использовании.

---

## Обработка 429 ответов

### Python

```python
import time
import requests

def request_with_backoff(method, url, headers, json=None, max_retries=5):
    for attempt in range(max_retries):
        response = requests.request(method, url, headers=headers, json=json)

        if response.status_code != 429:
            return response

        retry_after = response.headers.get("Retry-After")
        reset_at = response.headers.get("X-RateLimit-Reset")

        if retry_after:
            wait = int(retry_after)
        elif reset_at:
            wait = max(int(reset_at) - int(time.time()), 1)
        else:
            wait = 2 ** attempt

        print(f"429 triggered. Waiting {wait} seconds (attempt {attempt + 1})...")
        time.sleep(wait)

    raise Exception("Maximum retry attempts exhausted")
```

### JavaScript

```javascript
async function requestWithBackoff(url, options, maxRetries = 5) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const response = await fetch(url, options);

    if (response.status !== 429) {
      return response;
    }

    const retryAfter = response.headers.get("Retry-After");
    const resetAt = response.headers.get("X-RateLimit-Reset");
    const wait = retryAfter
      ? Number(retryAfter)
      : resetAt
        ? Math.max(Number(resetAt) - Math.floor(Date.now() / 1000), 1)
        : 2 ** attempt;

    console.log(`429 triggered. Waiting ${wait} seconds (attempt ${attempt + 1})...`);
    await new Promise(resolve => setTimeout(resolve, wait * 1000));
  }

  throw new Error("Maximum retry attempts exhausted");
}
```

## Лучшие практики

- **Реализовать повторные попытки экспоненциальной отсрочки**: сначала подождите 1 секунду, каждый раз удваивайте время ожидания и ограничьте максимальное время ожидания 32 секундами.
- **Предпочитайте заголовки `Retry-After` и `X-RateLimit-Reset`**: дождитесь сброса окна пределов.
- **Проектируйте параллелизм на уровне категорий**: по возможности распределяйте рабочую нагрузку по категориям — создание изображений и создание 3D-изображений имеют отдельные пулы.
- **Использовать пакетные запросы API**: используйте `POST /v3/tasks/list` вместо нескольких запросов `GET /v3/tasks/{task_id}`.
- **Опрос разумный**: ожидая завершения задачи, опрашивайте через разумные промежутки времени (каждые 1–2 секунды), а не заполняйте конечную точку запроса.
