Lingara Lingara مستندات راهنماها API کتابخانه‌ها برنامه‌ها ساخت نسخهٔ وب
زبان: فارسی

خطاها و تلاش دوباره

این صفحه از انگلیسی ترجمه شده است. اگر این دو با هم تفاوت داشته باشند، صفحهٔ انگلیسی درست است. خواندن صفحهٔ انگلیسی

هر شکستی که یک کتابخانه برمی‌گرداند یکی از چهار خطاست، و هر چهار نوع پایه مشترکی دارند، پس یک کنترل‌کننده می‌تواند همه را بگیرد.

  • خطای API. API درخواست را رد کرده است. این خطا وضعیت HTTP، یک code پایدار برای انشعاب منطق، و پیامی به زبانی که درخواست کرده‌اید را در خود دارد.
  • خطای OAuth. نقطه پایانی توکن اعتبارنامه‌های شما یا دامنه‌های دسترسی درخواستی را رد کرده است.
  • خطای نگهداری. API برای نگهداری به‌طور کوتاه در دسترس نیست.
  • خطای انتقال. هیچ پاسخ قابل استفاده‌ای نرسید: اتصال شکست خورد یا زمانش تمام شد، یا پاسخ خوانده نشد.

لغو یک فراخوانی خطا نیست. به شکل سازوکار لغو خود زبان شما ظاهر می‌شود.

چه چیزهایی دوباره امتحان می‌شوند

پاسخ 429 یا 503 که مدت انتظار را در سرآیند Retry-After با مقدار 60 ثانیه یا کمتر اعلام کند، دقیقاً پس از همان مدت دوباره امتحان می‌شود. هر فراخوانی حداکثر 3 بار تلاش می‌کند. با تنظیم حداکثر روی 1 می‌توانید تلاش دوباره را خاموش کنید.

هر چیز دیگری بی‌درنگ برگردانده می‌شود:

  • پاسخ 429 یا 503 بدون Retry-After؛
  • انتظاری بیش از 60 ثانیه، که کتابخانه آن را درون فراخوانی شما صرف نمی‌کند. خطا retry_after را در خود دارد، تا بتوانید تلاش دوباره را خودتان زمان‌بندی کنید؛
  • خطای انتقال، چون ممکن است درخواست پیش‌تر به API رسیده باشد؛
  • هر جریانی که رویدادی تحویل داده است.
زبان نمونه‌کد

TypeScript

import { ApiError, MaintenanceError, OAuthError, TransportError } from "@lingara/api";

try {
  await client.getUsage();
} catch (e) {
  if (e instanceof ApiError) {
    // A refusal from the API: e.status, e.code (stable) and e.message (localised).
    console.error(e.status, e.code, e.message, e.retryAfter ?? "");
  } else if (e instanceof OAuthError) {
    // The token endpoint refused the credentials or the scopes.
    console.error(e.status, e.error, e.description ?? "");
  } else if (e instanceof MaintenanceError) {
    console.error("under maintenance; retry after", e.retryAfter ?? "a while");
  } else if (e instanceof TransportError) {
    // No usable answer: connect, tls, reset, timeout, and so on.
    console.error("transport:", e.kind);
  } else {
    throw e;
  }
}

Rust

use lingara::Error;

let result = client.get_usage().await;
if let Some(wait) = result.as_ref().err().and_then(Error::retry_after) {
    eprintln!("the API asks you to retry after {wait:?}");
}
match result {
    Ok(usage) => println!("{} allowance rows", usage.allowance.len()),
    // A refusal from the API: status, code (stable) and message (localised).
    Err(Error::Api(e)) => eprintln!("{} {} {}", e.status, e.code, e.message),
    // The token endpoint refused the credentials or the scopes.
    Err(Error::OAuth(e)) => eprintln!("{} {} {}", e.status, e.error, e.description.unwrap_or_default()),
    Err(Error::Maintenance(_)) => eprintln!("the API is under maintenance"),
    // No usable answer: connect, tls, reset, timeout, and so on.
    Err(Error::Transport(e)) => eprintln!("transport: {}", e.kind),
    Err(other) => return Err(other.into()),
}

Go

_, err := client.GetUsage(ctx)
var apiErr *lingara.APIError
var oauthErr *lingara.OAuthError
var maintenance *lingara.MaintenanceError
var transport *lingara.TransportError
switch {
case err == nil:
case errors.As(err, &apiErr):
	// A refusal from the API: Status, Code (stable) and Message (localised).
	fmt.Println(apiErr.Status, apiErr.Code, apiErr.Message)
	if apiErr.RetryAfter != nil {
		fmt.Println("retry after", *apiErr.RetryAfter)
	}
case errors.As(err, &oauthErr):
	// The token endpoint refused the credentials or the scopes.
	fmt.Println(oauthErr.Status, oauthErr.ErrorCode, oauthErr.Description)
case errors.As(err, &maintenance):
	fmt.Println("under maintenance")
	if maintenance.RetryAfter != nil {
		fmt.Println("retry after", *maintenance.RetryAfter)
	}
case errors.As(err, &transport):
	// No usable answer: connect, tls, reset, timeout, and so on.
	fmt.Println("transport:", transport.Kind)
default:
	// ctx was cancelled or timed out: errors.Is(err, context.Canceled).
	fmt.Println(err)
}

Java

try {
  client.getUsage();
} catch (LingaraException e) {
  if (e instanceof ApiException api) {
    // A refusal from the API: status(), code() (stable) and getMessage() (localised).
    System.out.println(api.status() + " " + api.code() + " " + api.getMessage());
    api.retryAfter().ifPresent(wait -> System.out.println("retry after " + wait));
  } else if (e instanceof OAuthException oauth) {
    // The token endpoint refused the credentials or the scopes.
    System.out.println(oauth.status() + " " + oauth.error() + " " + oauth.description());
  } else if (e instanceof MaintenanceException maintenance) {
    System.out.println("under maintenance");
    maintenance.retryAfter().ifPresent(wait -> System.out.println("retry after " + wait));
  } else if (e instanceof TransportException transport) {
    // No usable answer: CONNECT, TLS, RESET, TIMEOUT, and so on.
    System.out.println("transport: " + transport.kind());
  }
}
// An interrupted call throws java.util.concurrent.CancellationException instead.

Kotlin

try {
    client.getUsage()
} catch (e: LingaraException) {
    when (e) {
        // A refusal from the API: status, code (stable) and message (localised).
        is ApiException -> println("${e.status} ${e.code} ${e.message}; retry after ${e.retryAfter}")
        // The token endpoint refused the credentials or the scopes.
        is OAuthException -> println("${e.status} ${e.error} ${e.description}")
        is MaintenanceException -> println("under maintenance; retry after ${e.retryAfter}")
        // No usable answer: CONNECT, TLS, RESET, TIMEOUT, and so on.
        is TransportException -> println("transport: ${e.kind}")
    }
}
// A cancelled call throws the caller's own CancellationException instead.

Ruby

begin
  client.get_usage
rescue Lingara::ApiError => e
  # A refusal from the API: status, code (stable) and message (localised).
  puts "#{e.status} #{e.code}: #{e.message}"
  puts "retry after #{e.retry_after}s" if e.retry_after
rescue Lingara::OAuthError => e
  # The token endpoint refused the credentials or the scopes.
  puts "#{e.status} #{e.error}: #{e.description}"
rescue Lingara::MaintenanceError => e
  puts "under maintenance"
  puts "retry after #{e.retry_after}s" if e.retry_after
rescue Lingara::TransportError => e
  # No usable answer: :connect, :tls, :reset, :timeout, and so on.
  puts "transport: #{e.kind}"
end

PHP

use Lingara\Exception\ApiException;
use Lingara\Exception\LingaraException;
use Lingara\Exception\MaintenanceException;
use Lingara\Exception\OAuthException;
use Lingara\Exception\TransportException;

try {
    $client->getUsage();
} catch (LingaraException $e) {
    if ($e instanceof ApiException) {
        // A refusal from the API: status, errorCode (stable) and message (localised).
        echo $e->status(), ' ', $e->errorCode(), ': ', $e->getMessage(), "\n";
        echo 'retry after: ', $e->retryAfter() ?? 'not given', "\n";
    } elseif ($e instanceof OAuthException) {
        // The token endpoint refused the credentials or the scopes.
        echo $e->status(), ' ', $e->error(), ': ', $e->description(), "\n";
    } elseif ($e instanceof MaintenanceException) {
        echo 'under maintenance; retry after: ', $e->retryAfter() ?? 'not given', "\n";
    } elseif ($e instanceof TransportException) {
        // No usable answer: connect, tls, reset, timeout, and so on.
        echo 'transport: ', $e->kind()->value, "\n";
    }
}