RFC-0031:类型化墓碑 | |
---|---|
状态 | 已拒绝 |
领域 |
|
说明 | 指示章程类型的功能和语法。 |
Gerrit 更改 | |
作者 | |
提交日期(年-月-日) | 2019-02-05 |
审核日期(年-月-日) | 2021-04-07 |
遭拒原因
此提案已被拒绝,因为它与服务发现的交互不畅 但也略高于预估的实现复杂程度。
与服务发现交互
Fuchsia 上很常见的一种模式是按名称请求特定协议,
(通过 fuchsia.io/Directory.Open
调用)。我们称之为服务发现。
在服务发现期间,客户端与实现
fuchsia.io/Directory
协议。当
服务器会找到所请求的适当服务,
通道服务器一端发送到请求的服务。这意味着
与某个服务器交互(支持 fuchsia.io/Directory
),则
另一个服务器(支持请求的服务)。
遗憾的是,服务发现对墓碑施加了强有力的限制。在
发生失败而导致发送章程表时,客户端无法判断
对等方发布了摘要 -- 是支持 fuchsia.io/Directory
的服务器,还是
请求的服务?
在实践中,服务发现可以包括远不止两个服务器, 。因此,墓碑必须非常通用,并且不能携带 网域特定的详细信息。从本质上讲,摘要很难满足 是所有可检测协议的最低标准。
作为该方案的一部分,为了消除这一限制,
让参与服务发现的所有协议构成一个
fuchsia/IsDiscoverable
协议。此协议将定义一个类型化的墓碑:
protocol IsDiscoverable {
epitaph zx.status;
};
fuchsia/IsDiscoverable
的子项都不能定义自定义墓碑。
从而正确捕获类型系统中的限制。具体而言,
部分:
一个协议只能有一个墓记类型声明 (包括以递归方式组合的任何及所有协议)。我们具体 防止两个具有相同 类型。
然而,让所有可发现的协议组合起来被认为不可行
这个全新的fuchsia/IsDiscoverable
。例如,静态强制执行
因为从设计上讲,服务发现是动态的。
与请求流水线交互
请求流水线模式 可以视为对服务发现模式的泛化, 对墓碑施加同样严格的限制。
实现复杂性
虽然 FIDL 功能具有复杂性(语言规则、JSON IR 扩展、 绑定代码、生成的代码、工效学设计), 而且它们的实用性很低。这种权衡 这真是让我们欢呼雀跃。
接下来该怎么做?
此部分代表作者的观点 (pascallouis@google.com)。
引入墓记时,陈述的目标是“提供 指示客户端到服务器连接被关闭的原因。
墓碑遗迹远远未达到这个目标,其用处也很有限。 过去依赖墓碑的协议也可以用自定义 事件,这些事件既没有上述任何缺点,也没有 载荷限制是由于优先级较低而施加的 FIDL 背后的原理。
摘要的一个好处是“彻底终止”协议的一部分,其中 服务器基本上可以确定,客户端对等体将会解除与通道的绑定, 请勿发出后续请求。
悬浮在上层,以引入适用于事件的 terminal
修饰符,
不再使用墓碑,而是转向自定义事件,同时又不会丢失
“彻底终止”属性。有了终端事件,库作者就会
可以随意定义事件的载荷。为了支持这一点,我们
会扩展传输格式,以分配事务
标头来指示
协议。收到标记为终端的消息后,客户端会
终止连接。客户应该
不知道事件(在复杂的请求管道场景中极有可能发生),
事务标头可以被客户端理解,而载荷
已舍弃。
摘要
我们建议:
- 新增在协议上指示墓碑类型的语法(我们不提供
更改墓碑仪的默认类型
zx.status
); - 一种向绑定公开墓碑类型的方法, 信息在代码生成过程中得到适当利用;
- 补充构成模型,以指定摘要类型 每个协议都是唯一的,并由组合继承。
我们希望在“leaf”上使用摘要输入即协议 由他人定义或由他人构成;或在“组合树”中使用一次 置于“顶部”的墓记类型或“root”协议。
设计初衷
tl;dr 我们喜欢类型。都是不错的选择。就会有更多类型
语法和错误类型
在 RFC-0053: Epitaphs 中,我们引入了 epitaphs 的概念, 一种机制,可让服务器在关闭 提供了连接关闭原因的指示”。墓碑 包含错误状态,该状态目前固定为 int32。时间 查看墓碑,我们选择将类型修复为 int32,以便使用 zx.status 目的是将“用户错误”折叠起来包含“协议错误”。
在 RFC-0060:错误处理中,我们专门引入了语法, 类型错误,尤其要注意“错误类型必须是 int32、uint32 或 枚举。"我们想要允许墓碑错误,以及 选择与错误处理的表示法匹配的表示法。
在 RFC-023:协议的组合模型中,我们引入了 语法来声明协议和编写协议。我们使用的语法 这里所提议的墓碑便遵循了这一风格。
我们将之前的所有决策视为 主张 (1) 和 (2)。
带墓碑的构成模型
主张 (3) 有两个方面:每个协议的墓记类型的唯一性, 行为
摘要的语义与特殊事件的语义相似, 响应类型对于每个协议都是唯一的。
组合中的行为遵循类似的思维方式,确认 墓碑Compose 类型。我们在下面讨论了一种替代定义, 缺点
通过允许墓记类型组合,我们会引入潜在的破坏
假设协议 ChildWithEpitaph
编写
FarawayParent
协议,并将其摘要类型定义为
SomeSpecificErrorCode
枚举。FarawayParent
是否应在事后决定
指定摘要类型,则禁止组合,并且
ChildWithEpitaph
的编译将会失败。
替代方法:墓碑不写词
另一种方法是考虑仅使用已定义的消息(方法和 事件)可以组合到其他协议中。在此替代模型中, 父协议定义表决类型,此类型将独立于 可能独立的子协议类型。例如,我们可以 允许使用以下定义:
protocol Parent {
epitaph ParentErrorCode;
};
protocol Child {
compose Parent;
epitaph ChildErrorCode;
};
由于我们不提供协议之间的任何关系(例如, 无进化性规则),则该替代模型有一些优点。它让很多 在同时使用口头输入和撰写的情况下,可以有更大的自由度。
不过,我们可以通过所有意图和目的来定义 因此应基于此选择权衡 这一设计目标。例如,如果我们引入一种正式的假设, 关系(“是”)时,协议是否构成另一个协议,并且两者都定义了一个 墓记类型不兼容,那么这些协议将立即使提交失败 测试:希望使用某种例证的客户无法应对 另一种墓碑类型。
因此,我们认为现在就限制 可以使用墓碑类型,这样便于扩展程序 明天。
设计
语法
我们扩展了语法,允许在协议中使用表头节 声明:
protocol SomeProtocol {
ExampleMethod(...) -> (...);
epitaph SomeErrorCode;
};
摘要节在语法上与 compose 节类似, 遵循为错误规范选择的语法。
正式地修改以下语法:
protocol-declaration = ( attribute-list ) , "protocol" , IDENTIFIER ,
"{" , ( protocol-member , ";" )* , "}" ;
protocol-member = ...
| "epitaph" type-constructor ; [NOTE]
NOTE: The epitaph stanza allows the more liberal type-constructor in the
grammar, but the compiler limits this to int32, uint32, or enum thereof. There
may be only one epitaph stanza per protocol definition.
ABI 和源代码兼容性
当我们引入摘要时,我们使用 希望我们将其限制为 32 位。将错误代码修复为 32 后来在引入错误语法时得到了确认。
在这里,我们将保留这个选择,并且如前所述,这会限制 转换为 int32、uint32 或其枚举。
因此,更改墓记类型(可能是从默认值更改为 指定的对象),不会修改 ABI 兼容性。
但是,更改表首类型很有可能破坏源代码级别 更改。绑定作者可能会破坏源代码兼容性。我们无法预见这一点 因为今天表记并未得到广泛使用。
JSON IR
我们向 definition/interface
对象添加类型为以下成员的代言:
definitions/type
。
例如,我们可能会:
{
"name": "example/SomeProtocol",
"epitaph": {
"kind": "primitive",
"subtype": "uint32"
},
"methods": [
{
"ordinal": 296942602,
墓记类型始终存在于接口声明中,并设置为
如果未指定,则默认为 zx.status
。
撰写墓碑
将一个协议组合为另一个协议时,系统会沿用墓记的类型。 例如,对于协议:
protocol Parent {
epitaph SomeErrorCode;
};
protocol Child {
compose Parent;
};
生成的 Parent
和 Child
的墓记类型为 SomeErrorCode
。
一个协议(包括 任何及所有组合的协议)。我们专门针对 具有相同类型的语义等效的记号类型声明。
此示例无效,应该无法编译:
protocol Parent1 {
epitaph SomeErrorCode1;
};
protocol Parent2 {
epitaph SomeErrorCode2;
};
protocol Child {
compose Parent1;
compose Parent2;
};
此示例也无效,应该无法编译:
protocol Parent {
epitaph SomeErrorCode;
};
protocol Child {
compose Parent;
epitaph SomeErrorCode;
};
实施策略
(由 FIDL 团队审核后确定。这项更改没有区别 (这是由于之前的许多更改所导致的)。
工效学设计
不适用
文档和示例
至少:
向后兼容性
FIDL 来源:由于我们正在扩展 语言语法。任何 FIDL 文件都不能包含“摘要类型构造函数”;节 。
JSON IR:向后兼容允许额外密钥的非严格解析器, 因为我们添加了“墓碑”键。
性能
不影响性能。
安全
没有影响,或者就额外的类型安全性而言略有正面影响。
测试
fidlc 中的单元测试,以及绑定生成测试。
缺点、替代方案和未知之处
不适用
早期艺术作品和参考资料
(如本文所述。)