AIP-151 耗时操作
编号 | 151 |
---|---|
原文链接 | https://google.aip.dev/151 |
状态 | 批准 |
创建日期 | 2019-07-25 |
更新日期 | 2025-02-04 |
有时,API可能需要提供一个消耗大量时间才能完成的方法。如果简单的阻塞客户端,等待任务运行,往往会给用户带来不好的体验;相反,最好给用户提供某种承诺,允许用户稍后检查进度。
耗时操作模式大致类似于Python Future或Node.js Promise:用户获得一个令牌,用来跟踪进度和获取结果。
指南
耗时较长的单个API方法 应当 返回google.longrunning.Operation对象,而非最终的应答消息。
// Create a book.
rpc CreateBook(CreateBookRequest) returns (google.longrunning.Operation) {
option (google.api.http) = {
post: "/v1/{parent=publishers/*}/books"
body: "book"
};
option (google.longrunning.operation_info) = {
response_type: "Book"
metadata_type: "OperationMetadata"
};
}
- 应答类型 必须 是
google.longrunning.Operation
。这个消息的定义 不得 复制到API定义文件中。- 应答 不得 是流式应答。
- 方法 必须 包含
google.longrunning.operation_info
注解,注解 必须 定义应答和元数据类型。- 应答和元数据类型 必须 在接口定义文件中定义,或者在该文件导入的文件中定义。
- 如果应答和元数据类型定义在另外的包中, 必须 使用完全限定消息名字。
- 应答类型 不应 使用
google.protobuf.Empty
(Delete方法除外),除非可以确定永远不会使用应答数据。如果将来可能添加应答数据,请为接口应答定义一个空消息。 - 元数据类型用于每次GetOperation调用时提供进度、部分失败等信息。元数据类型 不应 使用
google.protobuf.Empty
,除非确定永远不需要元数据。如果将来可能添加元数据,请为接口元数据定义一个空消息。
- 返回Operation消息的API 必须 实现Operations服务。单个API 不得 定义独立的耗时操作接口,避免不一致的情况。
- 如果接口支持仅验证模式,验证请求的应答 必须 是下列之一:
- 成功应答,包含已完成操作的
Operation
, 其done
域设置为true
,并在response
域中包含有效的(可能为空)、封装在google.protobuf.Any
中的应答消息。name
域 可以 为空,以免服务为验证成功场景维护状态。 - 立即返回的错误应答(通常是“错误请求”)
- 一个
Operation
, 其done
域设置为false
,表示耗时验证。此时name
域 必须 设定值,以便客户端轮询耗时验证结果,直到验证结束。成功的验证操作 必须 最终返回done
域为true
的Operation
,并在response
域中包含有效的(可能为空)、封装的应答消息。失败的验证操作 必须 最终返回done
域为true
的Operation
,并在error
域中提供错误细节。
- 成功应答,包含已完成操作的
注意 用户对“明显较长时间”的期望可能因任务内容而不同。一个好的经验法则是10秒钟。
标准方法
API标准方法Create、Update或Delete 可以 返回 Operation
(如果适用)。此时, operation_info
注解中的应答类型 必须 是标准方法的预期应答类型。
在使用耗时操作创建或删除资源时,资源 应当 包含在List和Get调用中;资源 应当 表明其可用状态,通常使用状态枚举。
并行操作
资源 可以 接受多个并行操作请求,但不强制这样做:
- 接受多个并行操作请求的资源 可以 将操作放入队列中,而非同时处理操作。
- 禁止并行操作的资源(在当前操作完成之前拒绝任何新操作请求) 必须 在用户试图并行操作时返回
ABORTED
错误,并包含解释原因的错误消息。 - 具有声明友好API的资源 可以 允许后续更新请求抢占当前操作。此时最新的更新操作开始处理,之前的操作被标记为
ABORTED
,并包含解释原因的错误消息。
过期失效
API 可以 允许资源在操作完成后,经过一定时间后过期失效。
注意 资源过期的一个好的经验法则是30天。
错误
耗时操作遇到错误无法启动, 必须 返回错误应答(AIP-193),和其他方法类似。
如果操作在执行过程中失败, 必须 返回错误应答(AIP-193),保存在 Operation.error
google.rpc.Status域。
在操作过程中发生的非终止性错误 可以 保存在元数据消息中, 相关域 必须 是符合 AIP-193 的 google.rpc.Status。
向后兼容
修改耗时操作的 response_type
或 metadata_type
是破坏性变更。
理由
仅验证行为
仅验证应答指南来源于客户端和服务器之间的矛盾:客户端从统一的、“完整形式”的操作中收益,而服务器则不愿意为琐碎操作维护额外状态。看起来有点违反直觉,仅仅验证一个请会产生更多的状态,而一个可以稍后获取的完整操作应答要么需要额外状态,要么需要“特殊的”唯一操作标识。本指南是一种折中方案:通过返回一个“已完成”操作对象,客户端可以使用现有逻辑来检查操作是否已成功完成(因此不需要为更新状态而轮询),而服务器则无需维护任何额外状态。
修订记录
- 2025-02-04 明确说明耗时操作过程中的故障传播行为。
- 2024-04-23 提供验证返回耗时操作对象的接口的模式。
- 2022-05-31 添加兼容性部分。
- 2020-08-24 明确说明应答不使用流式应答。
- 2020-06-24 添加并行操作指南。
- 2020-03-20 明确说明response_type和metadata_type都是必需域。
- 2019-11-22 添加关于metadata_type用途的简短说明。
- 2019-09-23 添加关于错误的指南。
- 2019-08-23 添加当消息定义在另外的包中时,使用完全限定消息名字的指南。
- 2019-08-01 将示例从“shelves”改为“publishers”,提供更好的资源所有权示例。