tommwq.work/aip

AIP-151 耗时操作

· [tommwq@126.com]
编号 151
原文链接 https://google.aip.dev/151
状态 批准
创建日期 2019-07-25
更新日期 2025-02-04

有时,API可能需要提供一个消耗大量时间才能完成的方法。如果简单的阻塞客户端,等待任务运行,往往会给用户带来不好的体验;相反,最好给用户提供某种承诺,允许用户稍后检查进度。

耗时操作模式大致类似于Python FutureNode.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.EmptyDelete方法除外),除非可以确定永远不会使用应答数据。如果将来可能添加应答数据,请为接口应答定义一个空消息。
    • 元数据类型用于每次GetOperation调用时提供进度、部分失败等信息。元数据类型 不应 使用 google.protobuf.Empty ,除非确定永远不需要元数据。如果将来可能添加元数据,请为接口元数据定义一个空消息。
  • 返回Operation消息的API 必须 实现Operations服务。单个API 不得 定义独立的耗时操作接口,避免不一致的情况。
  • 如果接口支持仅验证模式,验证请求的应答 必须 是下列之一:
    • 成功应答,包含已完成操作的 Operation , 其 done 域设置为 true ,并在 response 域中包含有效的(可能为空)、封装在 google.protobuf.Any 中的应答消息。 name可以 为空,以免服务为验证成功场景维护状态。
    • 立即返回的错误应答(通常是“错误请求”)
    • 一个 Operation , 其 done 域设置为 false ,表示耗时验证。此时 name必须 设定值,以便客户端轮询耗时验证结果,直到验证结束。成功的验证操作 必须 最终返回 done 域为 trueOperation ,并在 response 域中包含有效的(可能为空)、封装的应答消息。失败的验证操作 必须 最终返回 done 域为 trueOperation ,并在 error 域中提供错误细节。

注意 用户对“明显较长时间”的期望可能因任务内容而不同。一个好的经验法则是10秒钟。

标准方法

API标准方法CreateUpdateDelete 可以 返回 Operation (如果适用)。此时, operation_info 注解中的应答类型 必须 是标准方法的预期应答类型。

在使用耗时操作创建或删除资源时,资源 应当 包含在ListGet调用中;资源 应当 表明其可用状态,通常使用状态枚举

并行操作

资源 可以 接受多个并行操作请求,但不强制这样做:

  • 接受多个并行操作请求的资源 可以 将操作放入队列中,而非同时处理操作。
  • 禁止并行操作的资源(在当前操作完成之前拒绝任何新操作请求) 必须 在用户试图并行操作时返回 ABORTED 错误,并包含解释原因的错误消息。
  • 具有声明友好API的资源 可以 允许后续更新请求抢占当前操作。此时最新的更新操作开始处理,之前的操作被标记为 ABORTED ,并包含解释原因的错误消息。

过期失效

API 可以 允许资源在操作完成后,经过一定时间后过期失效。

注意 资源过期的一个好的经验法则是30天。

错误

耗时操作遇到错误无法启动, 必须 返回错误应答(AIP-193),和其他方法类似。

如果操作在执行过程中失败, 必须 返回错误应答(AIP-193),保存在 Operation.error google.rpc.Status域。

在操作过程中发生的非终止性错误 可以 保存在元数据消息中, 相关域 必须 是符合 AIP-193google.rpc.Status

向后兼容

修改耗时操作的 response_typemetadata_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”,提供更好的资源所有权示例。