त्रुटियाँ
हर विफलता raise होती है। अस्वीकार के लिए एक क्लास, जवाब न आने के लिए एक, और हर API error पर एक request id।
इसे पकड़ना
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किसी send पर आया permission_error आमतौर पर वर्कस्पेस का नहीं बल्कि कुंजी के send scope का मामला होता है, यानी कोई डोमेन या पता जो उसे दिया ही नहीं गया, इसीलिए यह नमूना वह छापता है जो addresses.list_all बताता है कि यह कुंजी किस पते से भेज सकती है।
हर तरह के अस्वीकार की अपनी subclass है, इसलिए एक rescue क्लास के आधार पर उन्हें चुन सकता है जिन्हें वह संभालता है और बाक़ी को ऊपर जाने दे सकता है।
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 द्वारा परिभाषित हर error का आधार, इसलिए rescue OpenEmail::Error उन सबको पकड़ता है। यह ArgumentError को नहीं पकड़ता। |
| OpenEmail::ApiError | API ने जवाब दिया, पर सफलता के साथ नहीं। इसमें status, type, code, param, doc_url, request_id, retry_after_seconds, fields और body होते हैं। जब type api_error हो, जैसे सर्वर की ख़राबी में होता है, तो यह ख़ुद इसी रूप में raise होता है, वरना अपने type की subclass के रूप में। |
| OpenEmail::InvalidRequestError, AuthenticationError, PermissionError, NotFoundError, ConflictError, ValidationError और RateLimitError | ApiError की subclasses, हर type के लिए एक: invalid_request_error, authentication_error, permission_error, not_found_error, conflict_error, validation_error और rate_limit_error। |
| OpenEmail::NetworkError | कोई जवाब नहीं आया: DNS, TLS, अस्वीकृत या टूटा कनेक्शन, या टाइमआउट। इसमें original होता है, यानी नीचे का exception, जो इसका cause भी है, और जब कारण टाइमआउट हो तो timeout? true होता है। |
| OpenEmail::WebhookSignatureError | OpenEmail.verify_webhook_signature ने एक डिलीवरी अस्वीकार कर दी। |
| ArgumentError | कुछ भी भेजे जाने से पहले raise होता है: ग़ायब या ग़लत बनी कुंजी, बेकार base_url:, ख़ाली id। यह सादी Ruby क्लास है, OpenEmail::Error नहीं, क्योंकि इसका मतलब है कि कॉल ख़ुद ग़लत है। |
ApiError में क्या होता है
messageString- API का अपना वाक्य, किसी व्यक्ति के लिए लिखा गया, जो जहाँ कोई ग़लत मान हो वहाँ उसका नाम लेता है। यह स्थिर पहचानकर्ता नहीं है, इसलिए शाखा `code` पर बनाएँ।
statusInteger- जवाब का HTTP status।
typeString- `OpenEmail::ERROR_TYPES` के आठ मानों में से एक, एक ऐसा सेट जो frozen है और बढ़ेगा नहीं। जब बॉडी कोई नाम नहीं देती, तो यह status से अनुमानित होता है।
codeString- विशिष्ट विफलता, जैसे `from_address_forbidden` या `invalid_email_address`। यह खुला और बढ़ने वाला है, इसलिए जिसे आप नहीं पहचानते उसे उसके `type` की तरह लें। जब बॉडी API का error envelope नहीं थी तो यह `unrecognised_response` होता है।
paramString or nil- वह फ़ील्ड जिसे अस्वीकार किया गया, `to.0` जैसे बिंदु वाले path के रूप में, जब विफलता किसी का नाम लेती है।
doc_urlString or nil- इस विफलता के बारे में एक पेज, जब API किसी का नाम लेता है।
request_idString or nil- वह id जिसके तहत सर्वर ने रिक्वेस्ट लॉग की, बॉडी से या `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` के साथ अस्वीकार किया हो। जब error कोई सूची न दे तो nil।
bodyHash or nil- पूरा error जवाब, पार्स किया हुआ, Symbol कुंजियों के साथ। जब वह ख़ाली था या JSON नहीं था तो nil।
| प्रेडिकेट मेथड | true कब |
|---|---|
| auth? | type authentication_error है, यानी 401: कोई key नहीं, गलत किस्म का क्रेडेंशियल, या ऐसी key जो हमने जारी नहीं की। |
| permission? | permission_error, यानी 403: असली key, पर उसके पास ज़रूरी scope या From पता नहीं। |
| scope_missing? | code insufficient_scope है, वह 403 जो अनुपस्थित scope का नाम बताता है। |
| invalid_request? | invalid_request_error, यानी 400: ऐसी रिक्वेस्ट जिसे समझा नहीं जा सका। आकार की सीमा से बड़ा संदेश 422 message_too_large बनकर लौटता है, इसलिए उसे पकड़ने वाला प्रेडिकेट validation? है। |
| validation? | validation_error, यानी 422: schema ने इसे अस्वीकार किया, और param उस फ़ील्ड का नाम बताता है। |
| not_found? | not_found_error, यानी 404: ऐसा कोई संसाधन नहीं। |
| conflict? | conflict_error, यानी 409: संसाधन उस बिंदु से आगे निकल चुका है जहाँ उसके साथ यह किया जा सकता था। |
| 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 पढ़ते हैं, यानी envelope का frozen हिस्सा, और हर subclass एक type का प्रतिनिधित्व करती है। code String ही रहता है, क्योंकि API गारंटी देता है कि यह खुला और बढ़ने वाला है, इसलिए जिसे आप नहीं पहचानते उसे उसके type की तरह लें। बंद सूची होने पर किसी नई विफलता को पढ़ने की क़ीमत gem अपग्रेड होती।
जो बॉडी API का error envelope नहीं है वह भी OpenEmail::ApiError raise करती है, जिसमें type status से अनुमानित होता है और code unrecognised_response रखा जाता है। जिस सफल जवाब की बॉडी JSON नहीं है वह भी यही raise करता है।
retryable? status का वर्णन करता है, आपकी कॉल का नहीं। दोहराने में सुरक्षित कॉल raise होने तक पहले ही दोबारा आज़माई जा चुकी होती है, और send_quota_exceeded या ai_quota_exceeded जैसा 429 तब तक उसी तरह विफल होता रहता है जब तक उसकी सीमा रीसेट न हो, इसलिए उस पर लूप चलाने के बजाय उसे किसी व्यक्ति को दिखाएँ।
आपका एडैप्टर जो exception raise करता है, वह कॉल द्वारा अनुमत सभी पुनः प्रयास ख़त्म होने के बाद OpenEmail::NetworkError बन जाता है, जिसमें मूल exception original और cause पर होता है। NameError, TypeError और ArgumentError अपवाद हैं: इनका मतलब एडैप्टर में bug है, इसलिए ये बिना बदले raise होते हैं और इन पर कभी पुनः प्रयास नहीं होता।
request_id
हर OpenEmail::ApiError वह request id साथ रखता है जो सर्वर ने भेजी, error बॉडी से या x-request-id हेडर से, और यही एकमात्र चीज़ है जो आपकी विफलता को सर्वर के लॉग की एक पंक्ति से जोड़ती है। सफल जवाब केवल पार्स की गई बॉडी लौटाता है, इसलिए उस पर पढ़ने को कोई request id नहीं होती।