use
但是,由于功能路由涉及一系列组件,仅仅因为组件 use
功能并不意味着它始终可用。它可能因各种原因而不可用:例如,如果链中的某个组件未路由该 capability,或者其中某个组件无法解析。
当组件 use
或路由某项功能时,可能对该功能是否可用有各种预期。在某些情况下,某项功能对于组件的运行至关重要:如果某个人创建的拓扑是无法将该功能路由到组件的,最好尽早检测到该故障以防止出现错误。但是,在其他情况下,组件也许可以容忍无该功能,或者在某些配置中可能不包含该功能。为了适应这些不同的场景,cml 为 use
、offer
和 expose
提供了一个 availability
选项,组件可以使用该选项来声明对功能可用性的预期。
选项
该框架支持 availability
的以下选项:
必需
最常用的 availability
选项是 required
,它表示组件始终期望相应功能可用,如果没有相应功能,则不可能正常工作。这是在未指定可用性的情况下自动设置的默认选项。
可选
optional
表示某项功能可能不存在于某些配置中。如果某个组件执行 use
某项可选功能但后来发现该功能不可用,那么该组件在没有它的情况下应该也能正常工作,例如,通过停用需要该功能的所有功能。
但是,如果 optional
功能在某些配置中不可用,框架会要求拓扑仍然包含该功能的完整路由,此功能在 void
中终止。这样,产品所有者应明确选择该功能是否可用(其路由在某个提供程序组件处终止)或不可用(其路由于 void
终止)。如果路由不完整,工具和诊断会将此报告为错误。
过渡风格
transitional
就像是 optional
的较弱版本。与 optional
一样,如果某个组件使用 transitional
功能,则应能够容忍没有该功能。不过,与 optional
不同的是,transitional
路由不需要在 void
中终止,并且如果 transitional
路由不完整或无效,工具和诊断将不会报告任何错误。
名称“transitional”意味着此选项对于软过渡很有用。例如,假设您有要替换为 EchoV2
的 Echo
协议。在此过渡的早期阶段,您可以将客户端更改为 use
且具有 transitional
可用性的新协议。稍后,一旦建立端到端路由,您就可以将可用性升级到 required
或 optional
。如果您曾尝试改用 optional
,工具和诊断会指出客户端组件的父级缺少 Echo2
的功能路由,而 transitional
则会抑制此类警告。
与目标相同
same_as_target
充当直通式:它会导致从路由的目标组件设置的任何可用性继承可用性。这对于传递大量功能的中间组件非常有用,这样一来,当在目标中更改了路由的 availability
时,不需要在源中进行任何更改。
由于对 capability 执行 use
的组件是其最终目的地,因此 same_as_target
并非 use
的有效选项。
库存状况比较
各可用性选项之间的“强度”存在相对顺序。从强到弱,顺序为:required > optional > transient
。same_as_target
不是其中的一部分,因为它是直通式:same_as_target
功能路由的强度实际上等于它从目标继承的任何可用性。
在许多情况下,将可用性从来源降级到目标是一种有效且有用的做法。例如,如果组件 X
向 Y
公开 required
capability,Y
可以选择将 capability 作为 optional
进行 use
,或者将 capability 作为 optional
提供给其他子项。offer
但从来源中升级可用性属于路由错误。如果发生这种情况,任何使用或路由该 capability 的尝试都将失败,同样地,如果路由链不完整,也会失败。这是一个错误,因为这意味着您尝试建立比来源保证的可用性更强的可用性保证。例如,如果某个组件的父级将某个 capability offer
设为 optional
,就没有将该 capability use
为 required
,因为这意味着父级已声明该 capability 可能不可用。
工具和诊断
设置可用性的主要作用是控制主机工具和诊断报告路由错误的方式。简而言之,这意味着 availability
越弱,其严格程度就越低。详细规范如下:
- 如果
required
功能路由不完整、无效或以void
结尾:- 审查会将此问题报告为路由错误。如果 build 配置要求通过测试,则会导致出现构建错误。
component_manager
会在 using 组件的作用域内记录一条WARNING
消息,以描述路由错误。
- 如果
optional
功能路由不完整或无效:- 审查会将此问题报告为路由错误。如果 build 配置要求通过测试,则会导致出现构建错误。
component_manager
会在 using 组件的作用域内记录一条INFO
消息,以描述路由错误。
- 如果
optional
功能路由以void
结尾:- 审查不会报告错误。
component_manager
可能会记录INFO
消息,但不会记录任何错误。
- 如果
transitional
功能路由不完整、无效或以void
结尾:- 系统不会记录任何错误或其他信息。
对于常规运行时行为,availability
没有任何影响。例如,假设某个组件尝试在其命名空间中对路由已损坏的命名空间执行 use
操作。如果协议以 required
或 optional
的形式路由,最终结果将相同:
- 该协议将显示在组件的命名空间中。
- 连接到 capability 的初始调用将会成功(假设标准单向 API 会像 rust 中的 connect_to_protocol 一样使用)。
component_manager
将尝试路由该功能。最终,路由将失败,相应通道将以NOT_FOUND
徽章关闭。
source_availability:未知
cml 具有一项额外功能,可用于自动生成 required
或 optional void
offer
,具体取决于是否包含具有来源子声明的 Cml 分片。如需详细了解此功能,请参阅构建文档。
示例
以下示例说明了本文档中介绍的概念。
此示例中有三个组件:
echo_client
,它会尝试使用echo_server
提供的各种协议echo_server
:提供一些协议echo_realm
,echo_client
和echo_server
的父级,用于将这两者关联起来
我们来看看他们的 Cml 文件:
// echo_client.cml
{
...
use: [
{ protocol: "fuchsia.example.Echo" },
{
protocol: "fuchsia.example.EchoV2",
availability: "transitional",
},
{
protocol: "fuchsia.example.Stats",
availability: "optional",
},
],
}
// echo_server.cml
{
...
capabilities: [
{ protocol: "fuchsia.example.Echo" },
],
expose: [
{
protocol: "fuchsia.example.Echo",
from: "self",
},
],
}
// echo_realm.cml
{
offer: [
{
protocol: "fuchsia.example.Echo",
from: "#echo_server",
to: "#echo_client",
availability: "required",
},
{
protocol: "fuchsia.example.Stats",
from: "void",
to: "#echo_client",
availability: "optional",
},
],
children: [
{
name: "echo_server",
url: "echo_server#meta/echo_server.cm",
},
{
name: "echo_client",
url: "echo_client#meta/echo_client.cm",
},
],
}
回想一下,如果省略 availability
,则默认为 required
。使用此拓扑时,行为如下:
echo_client
将能够成功连接到fuchsia.example.Echo
。echo_client
将无法连接到fuchsia.example.EchoV2
或fuchsia.example.Stats
。- 工具和诊断不会记录错误。
fuchsia.example.Stats
没有错误,因为它的状态为optional
并路由到void
。- “
fuchsia.example.Stats
”没有错误,因为它是transient
。
现在,我们看看不同版本会发生什么情况:
// echo_client.cml
{
...
use: [
{ protocol: "fuchsia.example.Echo" },
{
protocol: "fuchsia.example.EchoV2",
availability: "transitional",
},
{
protocol: "fuchsia.example.Stats",
availability: "optional",
},
],
}
// echo_server.cml
{
...
capabilities: [
{
protocol: [
"fuchsia.example.Echo",
"fuchsia.example.EchoV2",
"fuchsia.example.Stats",
],
},
],
expose: [
{
protocol: [
"fuchsia.example.Echo",
"fuchsia.example.EchoV2",
],
from: "self",
},
{
protocol: "fuchsia.example.Stats",
from: "self",
availability: "optional",
},
],
}
// echo_realm.cml
{
offer: [
{
protocol: [
"fuchsia.example.Echo",
"fuchsia.example.EchoV2",
],
from: "#echo_server",
to: "#echo_client",
availability: "same_as_target",
},
{
protocol: "fuchsia.example.Stats",
from: "#echo_server",
to: "#echo_client",
availability: "optional",
},
],
children: [
{
name: "echo_server",
url: "echo_server#meta/echo_server.cm",
},
{
name: "echo_client",
url: "echo_client#meta/echo_client.cm",
},
],
}
现在:
echo_client
将能够成功连接到fuchsia.example.Echo
、fuchsia.example.EchoV2
和fuchsia.example.Stats
。- 每个路由在具有不同的
availability
时都是完整的,并在真实组件中终止。 - 对于每个路由,源和目标之间的可用性都通过了比较检查
- 每个路由在具有不同的
- 工具和诊断功能不会记录错误,因为所有路线都已完成。