Перехоплюйте помилки SDK

PHP

Що несе помилка SDK, як перехоплювати її за типом і розгалужуватися за кодом і які помилки кажуть, що запуск міг коштувати грошей.

5 хв читання

Виклик SDK, який API відхиляє або який лишається без відповіді, кидає помилку. Усі помилки SDK мають один кореневий тип, і кожна зберігає код API, тому один catch перехоплює їх усі, а код їх розрізняє.

Що несе помилка

ЩоPHPNode.js
Код APIerrorCodecode
HTTP-статусstatusCodestatus
Фраза для людиниgetMessage()message
Подробиці, де код їх несеdetailsdetails
Ідентифікатор запитуrequestIdrequestId
Скільки секунд просив зачекати відхилений 429 або 503retryAfterSecondsretryAfterSeconds
  • Розгалужуйтеся за кодом. Повідомлення — для людини, і його формулювання може змінюватися.

  • Помилка з’єднання й тайм-аут клієнта не мають ні коду, ні статусу: відповідь API не прочитано. Помилки, які SDK кидає сам — до надсилання запиту або на відповіді, яку він не може прочитати, — мають власний код SDK; їх перелічує стаття Типи помилок.

  • Ідентифікатор запиту — те, що спитає підтримка. Це заголовок X-Request-Id відповіді.

Перехоплювати за типом, розгалужуватися за кодом

PHP
use Slen\Sdk\Exceptions\OperationUncertainException;
use Slen\Sdk\Exceptions\SlenException;
use Slen\Sdk\Exceptions\SpendRefusedException;
use Slen\Sdk\Modules\Operations\Options\ExecuteOptions;

$input = ['messages' => [['role' => 'user', 'content' => 'Write a short follow-up email.']]];

try {
    $execution = $slen->operations()->execute('generate_email', $input, new ExecuteOptions(idempotencyKey: 'order-42:email'));

    echo $execution->status->value, PHP_EOL;
} catch (SpendRefusedException $error) {
    // The spend was refused, and the code says what refused it.
    echo 'refused: ', $error->errorCode, PHP_EOL;
} catch (OperationUncertainException $error) {
    // A provider was called and its answer was lost: the call may have been paid for.
    echo 'uncertain, request ', $error->requestId, PHP_EOL;
} catch (SlenException $error) {
    echo $error->statusCode, ' ', $error->errorCode, ': ', $error->getMessage(), PHP_EOL;
}
  • Перехоплюйте вузький тип раніше за широкий: catch кореневого типу перехоплює й відхилену витрату.

  • Відмови у витраті — одна родина; що робити з кожною, каже стаття Коли витрату відхилено.

  • Який тип отримує кожен код, називає стаття Типи помилок.

  • Помилка вашого власного коду — не помилка SDK. Пропустіть її далі.

SDK сам надсилає запит ще раз лише тоді, коли відповіді не було, після 429 або 503 — Повтори й тайм-аути. Кидає він помилку останньої спроби. Будь-яка інша відповідь API, яка є помилкою, кидається одразу. Очікування саме читає статус ще раз після невдалого читання — як описує стаття Асинхронні запуски й очікування.

Чи коштував запуск грошей

Гроші запуску — це гроші викликів моделей, які зробив його флоу. Тип каже, чи могли бути витрачені гроші і, отже, чи можна надіслати виклик ще раз.

  • Відхилено, перш ніж щось виконалося — SpendRefusedException, PolicyDeniedException, AuthenticationException, InvalidRequestException, CustomerNotFoundException, RateLimitException та їхні двійники в Node.js. Нічого не виконалося й нічого не зарезервовано. Той самий запит відхиляється знову, поки не зміниться те, що його відхилило: бюджет почне наступне вікно, клієнта поповнять, ключ отримає дозвіл. Ліміт запитів пропускає після паузи, про яку просить, а concurrency_limit_exceeded — коли виклик, що триває, закінчиться.

  • Зайнятий ключ — IdempotencyConflictException, IdempotencyConflictError. Із кодом idempotency_in_progress перший запит під цим ключем ще не закінчився: надішліть виклик ще раз пізніше під тим самим ключем. Із кодом idempotency_conflict ключ належить іншому запиту: надішліть свій під новим ключем.

  • Сам Slen — ServiceUnavailableException, ServiceUnavailableError. Запит не виконано, і провайдера не викликали. Надішліть його ще раз пізніше під тим самим ключем.

  • Немає відповіді — TimeoutException, ConnectionException та їхні двійники в Node.js, без коду. Невідомо, чи зробив Slen роботу. SDK уже надіслав запит ще раз під тим самим ключем; надсилайте його ще раз лише під цим ключем, і Slen зробить роботу один раз.

  • Невідомий результат — OperationUncertainException, OperationUncertainError. Провайдера викликали, а його відповідь втрачено, тому за виклик могли заплатити. Не надсилайте запуск ще раз під новим ключем — Коли результат невідомий.

  • Провайдер — ProviderException, ProviderError. Із кодом provider_error, provider_unavailable, provider_rate_limit, provider_timeout, provider_not_configured або pool_exhausted виклик моделі, який не вдався, повернув свої гроші. З будь-яким іншим кодом або без коду помилка не каже, як далеко зайшов запуск: вважайте це невідомим результатом.

  • Флоу — FlowRuntimeException, FlowRuntimeError і будь-яка помилка з operations.execute() після того, як флоу почав виконуватися: відмова чи збій на пізнішому вузлі, ledger_unavailable, execution_timeout і background_hold_expired. Виклики моделей, зроблені до помилки, оплачено. Повтор під новим ключем платить за них знову; під тим самим ключем Slen відповідає виконанням таким, яким воно закінчилося.

  • Нечитабельна відповідь — InvalidResponseException, InvalidResponseError. API відповів 2xx, який не можна прочитати, тому виклик міг пройти. Надсилайте його ще раз лише під тим самим ключем.

Рух кредитів, що лишився без відповіді, під своїм ключем відбувається один раз: надішліть його ще раз під тим самим ключем.

Відмова, прочитана пізніше

operations.execute() кидає помилку, якою відповіли на його запит. Виконання, яке відкрив запит, закрите й зберігає код. Якщо прочитати його пізніше, це вже не помилка: повтор запиту під його ключем, очікування й читання статусу повертають виконання, а його статус і error_code кажуть, чим воно закінчилося.

PHP
$again = $slen->operations()->execute('generate_email', $input, new ExecuteOptions(idempotencyKey: 'order-42:email'));

if ($again->isRejected()) {
    echo 'rejected: ', $again->errorCode, PHP_EOL;
}

isRejected() повертає true, коли статус — rejected, а errorCode зберігає код.

Флоу може відмовити й навмисно. Вузол Відхилити запит відповідає виконанням зі статусом rejected, а не помилкою. Тому код, який реагує на відмову, обробляє і те, і те: catch і статус того, що повернулося. Статуси виконання перелічує стаття Швидкий старт.

Що читати далі