RFC-0060:錯誤處理

RFC-0060:錯誤處理
狀態已接受
領域
  • FIDL
說明

API 通常需要指出無法完成要求。通常具有與錯誤相關的實用背景資訊,可讓呼叫端採取修正動作。這提議的語法可讓 FIDL 介面說明回報錯誤的方式。

作者
提交日期 (年-月-日)2018-09-18
審查日期 (年-月-日)2018-12-06

摘要

API 通常需要指出無法完成要求。 通常還會提供與錯誤相關聯的有用資訊 可讓呼叫端採取修正措施。 這提出一種語法,可讓 FIDL 介面說明錯誤程度 將遭到檢舉。

提振精神

大多數程式設計語言都提供錯誤處理結構,例如例外狀況、 Future/Promise、結果類型或錯誤類型。 以不使用語言撰寫的 API,通常能自行產生慣例 例如 errnozx_status_tGError

FIDL 方法可傳回多個值,因此一種方法可能會傳回值和 錯誤碼,但以不一致的方式隨機完成。 介面作者通常會先將錯誤代碼放在 方法之前。 但大約有 20% 的時間是 相反, 有時介面會傳回同時包含狀態碼和struct 結果。 狀態會以 boolintenumstringstruct 表示。

這樣的 API 多樣性,讓開發人員難以理解。 缺少明確語法,無法區分方法結果與錯誤 資訊導致無法產生慣用的繫結

設計

我們應該擴充 FIDL 方法語法,以允許介面描述 不同的 result 傳回類型和 error 傳回類型。 事件一律不會有錯誤類型。 語法如下所示:

interface Example {
  // This method returns no values, failures or completion.
  1: NoReturn();

  // This method returns no values or failures but informs
  // clients of completion.
  2: Completion() -> ();

  // This method returns a single value.
  3: SingleValue() -> (int32 result);

  // This method returns multiple values.
  4: MultipleValue() -> (int32 foo, string bar);

  // This method doesn't return any values but can indicate a
  // failure reason.
  5: CanFail() -> () error int32;

  // This method can succeed with a result or fail with a reason.
  6: WinOrLose() -> (string result) error ExampleError;
};

未宣告錯誤類型的方法會序列化並完全綁定 但我們現在更是如此 傳回引數會編碼為 FIDL struct

宣告錯誤類型的方法會序列化為 以及結果和錯誤傳回類型 因此,

interface Example {
  1: Method() -> (string result, string other_result) error int32;
};

編碼方式如下:

struct ExampleMethodResult {
  string result;
  string other_result;
};
[Result]
union ExampleMethodReturn {
  ExampleMethodResult result;
  int32 err;
};
interface Example {
  1: Method() -> (ExampleMethodReturn return);
};

錯誤類型必須是其中一種類型的 int32uint32enum

理想情況下,所有現有介面都將與原始碼及二進位檔相容 他們就會改用新的錯誤語法

在 FIDL IR 中,代表結果或錯誤的聯集會有所不同 因為前端編譯器會附加 [Result] 屬性。 現有的語言繫結仍會繼續運作,但可以進行更新,以便支援。 更多慣用語言功能,用於代表失敗的方法呼叫。

我們提議 Dart 透過 Future 錯誤傳回失敗。 這些物件應為 package:fidl 中定義的特殊 Error 類型子類別 以便輕鬆區分應用程式層級錯誤與繫結 以及通訊協定錯誤

Rust 應使用 std::result::Result。 如果 C++ 曾經變得真實的東西,那麼 C++ 可以使用 std::expected,但在 同時,我們也能導入足夠的提案 FIDL。 Go 繫結應使用自訂錯誤類型來傳回錯誤。

執行策略

這會在下列步驟中實作:

  • 更新 fidlc 以支援新的語法。
  • 請確認它定義了正確的編碼。
  • 更新 FIDL 語言說明文件。
  • 更新繫結,使用更慣用的錯誤處理機制。
  • 更新 FIDL 相容性測試介面 來測試錯誤,並支援所有語言繫結。
  • 驗證語言繫結是否正確互通。
  • 更新說明文件。
  • 鼓勵介面作者改進介面,以出錯 傳回類型。

說明文件和範例

這是 FIDL 的重大異動。 語言無線格式說明文件必須更新為 描述新語法以及其序列化方式。 您必須更新 FIDL 教學課程,以舉例說明 正確使用錯誤傳回功能。 API 技術評分量表必須更新,以說明適當用途 這項功能

回溯相容性

大多數現有的 FIDL 介面都仍與這項變更相容。 唯一的破壞性變更是 error 成為保留字詞。

成效

對效能的影響不大。

安全性

標準化 Error Reporting 語意,簡化呼叫 FIDL 的程式碼 方法。 明確比隱含更好。

測試

這需要測試 fidlc、相容性測試,以及可能的語言 繫結特定測試,確保繫結合乎原則。

缺點、替代方案和未知

這會增加程式語言的複雜度,但其實複雜性僅 已在介面中隱含表示的語意。

這個提案不包括標準 錯誤列舉,用於說明錯誤類別,並向呼叫端的呼叫端提供提示 如何繼續。 這個模式常見於 errnozx_status_tHTTP 狀態 代碼。 這些範例會嘗試擷取更多詳細資料,超出我們認為適當的範圍。 grpc_status_code 更適合我們 大略錯誤 我們考慮在標準 FIDL 程式庫中加入一個通用錯誤列舉, 讓介面編寫者能夠選用,而不必自行發明。

開發人員針對如何摺疊應用程式錯誤 (例如,記錄 找不到) 出現傳輸層級 FIDL 錯誤 (例如訊息剖析失敗)。 目前所有傳輸層級 FIDL 錯誤都會導致管道關閉,因此 不需要折疊錯誤代碼。 我們希望能夠復原,但請放心, 。 將錯誤保持在 32 位元內,可能會有很多餘裕導致錯誤折疊。

本提案的先前版本允許錯誤為任意資料類型。 這可能有助於某些反模式,例如傳回錯誤訊息字串 因為我們力求和八分音符同步錯誤 所以我們的彈性有限 然後重新檢查錯誤折疊狀態。 目前,我們正在採用較保守的錯誤表示法概念。

既有藝術品和參考資料