پرش به مستندات
Ruby

خطاها

هر شکستی raise می‌شود. یک کلاس برای رد شدن، یکی برای نرسیدن پاسخ، و یک شناسهٔ درخواست روی هر خطای API.

گرفتن یک خطا

rescue_errors.rb
message = {from: "[email protected]", to: "[email protected]", subject: "Your September invoice", text: "Invoice attached."} begin  client.emails.send(message)rescue OpenEmail::ApiError => error  warn "#{error.code} #{error.param} #{error.message}" if error.validation?  warn client.addresses.list_all.addresses.inspect if error.permission?  warn "try again in #{error.retry_after_seconds} seconds" if error.rate_limited?   warn "#{error.status} #{error.request_id}"  raiserescue OpenEmail::NetworkError => error  warn "no answer in time" if error.timeout?  raiseend

یک permission_error روی ارسال معمولاً به اسکوپ ارسالِ خودِ کلید برمی‌گردد، به دامنه یا آدرسی که به آن داده نشده، نه به فضای کاری، و به همین دلیل است که نمونه چاپ می‌کند addresses.list_all می‌گوید این کلید از چه آدرس‌هایی می‌تواند بفرستد.

هر نوع رد شدن زیرکلاس خودش را دارد، پس یک rescue می‌تواند آن‌هایی را که رسیدگی می‌کند بر اساس کلاس انتخاب کند و بگذارد بقیه به بالا بروند.

rescue_by_class.rb
message = {from: "[email protected]", to: "[email protected]", subject: "Your September invoice", text: "Invoice attached."} begin  client.emails.send(message)rescue OpenEmail::ValidationError => error  warn "#{error.param}: #{error.message}"rescue OpenEmail::AuthenticationError, OpenEmail::PermissionError => error  warn "the key cannot do this: #{error.code}"  raiserescue OpenEmail::Error => error  warn "#{error.class}: #{error.message}"  raiseend

کلاس‌ها

کلاسچه زمانی
OpenEmail::Errorپایهٔ همهٔ خطاهایی که gem تعریف می‌کند، پس rescue OpenEmail::Error همهٔ آن‌ها را می‌گیرد. ArgumentError را نمی‌گیرد.
OpenEmail::ApiErrorAPI پاسخ داده است، اما نه با موفقیت. حامل status، type، code، param، doc_url، request_id، retry_after_seconds، fields و body است. وقتی type برابر api_error باشد، مانند خطای سرور، با همین کلاس raise می‌شود، و در غیر این صورت با زیرکلاسِ متناظر با type آن.
OpenEmail::InvalidRequestError، AuthenticationError، PermissionError، NotFoundError، ConflictError، ValidationError و RateLimitErrorزیرکلاس‌های ApiError، یکی برای هر type: invalid_request_error، authentication_error، permission_error، not_found_error، conflict_error، validation_error و rate_limit_error.
OpenEmail::NetworkErrorهیچ پاسخی نرسیده است: DNS، TLS، اتصالی که رد یا قطع شده، یا پایان مهلت. حامل original است، یعنی استثنای زیرین که cause آن هم هست، و وقتی دلیل، پایان مهلت بوده باشد timeout? برابر true است.
OpenEmail::WebhookSignatureErrorOpenEmail.verify_webhook_signature یک تحویل را رد کرده است.
ArgumentErrorپیش از آنکه چیزی فرستاده شود raise می‌شود: کلیدِ نبوده یا بدشکل، یک base_url: غیرقابل‌استفاده، یک شناسهٔ خالی. همان کلاس سادهٔ Ruby است، نه یک OpenEmail::Error، چون یعنی خودِ فراخوانی نادرست است.

آنچه یک ApiError با خود دارد

messageString
جملهٔ خودِ API، نوشته‌شده برای آدم، که مقدار خطاساز را در جایی که وجود دارد نام می‌برد. شناسه‌ای پایدار نیست، پس روی `code` شاخه بزنید.
statusInteger
وضعیت HTTP پاسخ.
typeString
یکی از هشت مقدار در `OpenEmail::ERROR_TYPES`، مجموعه‌ای که ثابت است و بزرگ‌تر نخواهد شد. وقتی بدنه هیچ‌کدام را نام نبرد، از وضعیت استنتاج می‌شود.
codeString
شکست مشخص، مانند `from_address_forbidden` یا `invalid_email_address`. باز و افزودنی است، پس با کدی که نمی‌شناسید مثل `type` خودش رفتار کنید. وقتی بدنه پاکت خطای API نبوده باشد، برابر `unrecognised_response` است.
paramString or nil
فیلدی که رد شده، به‌صورت مسیری نقطه‌دار مانند `to.0`، وقتی شکست فیلدی را نام ببرد.
doc_urlString or nil
صفحه‌ای دربارهٔ این شکست، وقتی API صفحه‌ای را نام ببرد.
request_idString or nil
شناسه‌ای که سرور درخواست را با آن در لاگ ثبت کرده، از بدنه یا از سرآیند `x-request-id`.
retry_after_secondsInteger, Float or nil
انتظاری که سرور در `Retry-After` خواسته، برحسب ثانیه، چه عدد فرستاده باشد چه تاریخ. وقتی چیزی نفرستاده باشد nil است.
fieldsArray<Hash> or nil
یک Hash برای هر مشکل، هرکدام با `key` و `error`، مانند `{key: "email", error: "email"}` وقتی `forms.subscribe` پاسخ‌ها را با یک 422 `invalid_form_submission` رد کرده باشد. وقتی خطا هیچ موردی را فهرست نکند nil است.
bodyHash or nil
کل پاسخ خطا، تجزیه‌شده، با کلیدهای Symbol. وقتی خالی بوده یا JSON نبوده nil است.
متد پرسشیچه زمانی true است
auth?type برابر authentication_error است، یک 401 Unauthorized: نبودن کلید، نوع نادرست اعتبارنامه، یا کلیدی که ما صادرش نکرده‌ایم.
permission?permission_error، یک 403 Forbidden: کلیدی واقعی بدون اسکوپ یا بدون آدرس From مورد نیازش.
scope_missing?code برابر insufficient_scope است، همان 403 Forbidden که اسکوپ غایب را نام می‌برد.
invalid_request?invalid_request_error، یک 400: درخواستی که قابل فهم نبوده است. پیامی فراتر از سقف اندازه به‌صورت یک 422 با message_too_large برمی‌گردد، پس validation? متد پرسشی‌ای است که آن را می‌گیرد.
validation?validation_error، یک 422: اسکیما آن را نپذیرفته است و param نام فیلد را می‌گوید.
not_found?not_found_error، یک 404 Not Found: چنین منبعی وجود ندارد.
conflict?conflict_error، یک 409 Conflict: منبع از نقطه‌ای گذشته است که بتوان این کار را روی آن انجام داد.
rate_limited?rate_limit_error، یک 429. وقتی سرور مدتی را نام برده باشد، retry_after_seconds آن انتظار را نگه می‌دارد.
server_error?status برابر 500 یا بالاتر است. اگر با پشتیبانی تماس گرفتید، request_id را ذکر کنید.
retryable?status یکی از 408، 429، 500، 502، 503 یا 504 است.
step_up_required?code برابر step_up_required است، همان 403 که توکن دسترسی OAuth پیش از یک تغییر حساس می‌گیرد تا وقتی شخص کدی را تأیید کند.

بیشتر متدهای پرسشی type را می‌خوانند، یعنی نیمهٔ ثابتِ پاکت، و هر زیرکلاس نمایندهٔ یک type است. code یک String باقی می‌ماند، چون API تضمین می‌کند که باز و افزودنی است، پس با کدی که نمی‌شناسید مطابق type آن رفتار کنید. یک فهرست بسته، بهای خواندن یک حالت شکست تازه را به ارتقای gem تبدیل می‌کرد.

بدنه‌ای که پاکت خطای API نباشد باز هم یک OpenEmail::ApiError را raise می‌کند، با type استنتاج‌شده از وضعیت و code برابر unrecognised_response. پاسخ موفقی که بدنه‌اش JSON نباشد نیز همین خطا را raise می‌کند.

retryable? وضعیت را توصیف می‌کند، نه فراخوانی شما را. فراخوانی‌ای که تکرارش بی‌خطر است، تا زمانی که خطا raise کند دوباره تلاش شده است، و یک 429 مانند send_quota_exceeded یا ai_quota_exceeded تا وقتی سهمیه‌اش بازنشانی نشود به همان شکل شکست می‌خورد، پس آن را به یک شخص نشان دهید، نه اینکه روی آن حلقه بزنید.

استثنایی که آداپتور شما raise کند، پس از مصرف شدن تلاش‌های دوباره‌ای که فراخوانی اجازه می‌دهد، به یک OpenEmail::NetworkError تبدیل می‌شود که استثنای اصلی روی original و cause آن است. NameError، TypeError و ArgumentError مستثنا هستند: یعنی باگی در آداپتور، پس بی‌تغییر raise می‌شوند و هرگز دوباره تلاش نمی‌شوند.

request_id

هر OpenEmail::ApiError شناسهٔ درخواستی را که سرور فرستاده است با خود دارد، از بدنهٔ خطا یا از سرآیند x-request-id، و تنها چیزی است که شکست شما را به یک سطر در لاگ سرور گره می‌زند. یک پاسخ موفق فقط بدنهٔ تجزیه‌شده را برمی‌گرداند، پس روی آن شناسهٔ درخواستی برای خواندن وجود ندارد.