Skip to main content
网络可能在请求中途失败。关键问题是:如果您重试,是否会有事情发生两次?在 Maple 中,您最常重试的写入操作都被设计为可安全重复,因此遇到超时,您无需先核对状态就可以直接重试。
此 API 没有 Idempotency-Key 请求头。对于订单、菜单和事件,安全性是每个操作自身的属性(详见下文),无需逐个请求选择启用。唯一需要您发送键的地方是预订和候位写入,它们使用请求体中的 idempotency_key(见下文)。

订单决策是重放安全的

重复发送订单决策(accept、deny、ready、complete、cancel 或 status)会返回相同的确认,不会重复产生副作用:
如果您发送了 accept 但响应超时,请再发送一次。订单只会被接受一次,无论哪种情况您都会收到 { "status": "received" }。这样,一个简单的“遇到暂时性错误就重试”的循环就是正确的,您这一侧无需做任何额外记录。

发布菜单是一次差异应用

菜单发布描述的是整份菜单的目标状态,并以您的 externalId 为键,按与当前已发布内容的差异来应用:
  • 重新发布完全相同的文档不会产生任何变化。
  • 对象标识通过 externalId 在多次发布之间保持稳定,因此重新发布不会重建或频繁变动对象。
  • 校验是全有或全无:返回 400 时不会更改任何内容,因此发布失败后菜单保持原样。
所以,如果发布超时,重新发送同一份文档是安全的。请参阅发布菜单。

预订写入携带 idempotency_key

创建、更改或取消预订(POST /v1/bookings、POST /v1/bookings/{id}/change、POST /v1/bookings/{id}/cancel),以场所身份取消预订(POST /v1/bookings/{id}/venue_cancel),以及为散客安排入座(POST /v1/locations/{locationId}/walk_ins),都需要在请求体中提供 idempotency_key,其范围限定在您的应用内。与候位加入一样,散客入座的键属于您的应用,在其所有门店间通用。键必须包含 1–255 个字符。对于 Maple 原生预订,事件记录会在同一个事务中记录该写入及其重放结果:
  • 使用相同的键和相同的请求重试,会重放最初的结果:您会得到同一个 booking,不会重复预订、改期或取消。
  • 相同的键搭配不同的请求(不同的客人、时段或备注)会返回 409,并带有 code: "idempotency_key_reused"。请为每次要执行的写入生成新的键;UUID 即可。
重试会返回同一个预订标识,而不会重新应用变更;响应是从当前预订中读回的。键自首次占用起有 24 小时的重放窗口。重放会先于 expected_version 被检查,因为在原始写入成功后,expected_version 往往已经过期。 原生和第三方服务商的保留(hold)都会被持久化,并归获取它们的应用所有。重复提交同一个 slot_token 会重放该应用仍有效的保留,而不会再占用新的锁。其他应用无法使用或释放它,即使在共同授权的门店也是如此。未知的服务商保留在经过保守的 24 小时不活动隔离期后,会释放其配额预留,这与其保留的审计记录无关;已过期的操作无法通过重试恢复。

由第三方服务商支持的写入

对于 OpenTable,Maple 会在向服务商发起 I/O 之前,持久地占用该键和请求摘要,并使用同一个稳定的服务商请求 ID。待处理的更改或取消还会为镜像预订预留,以防其他合作伙伴写入。成功后,Maple 会同时记录镜像和重放结果。暂时性的镜像失败会同步重试;后台对账程序会修复未完成的工作。 服务商超时会在结果尚未确定时返回 409 operation_in_progress。请在 details.retry_after 秒后,使用相同的请求和键重试。在使用原始服务商请求 ID 重复执行预订写入之前,Maple 会先执行一次对账读取。已完成的写入会直接重放,不会再次调用服务商。
未解决的待处理键在其 24 小时自动重放窗口结束后不会被回收。如果 details.reason 为 replay_window_expired,请停止自动重试,并携带 details.operation_id 联系 Maple。不要为了绕开不确定的结果而生成新的键。
预订配置则改用内容寻址的发布方式:相同的配置无需显式的键,也不会产生任何变化。状态类场所操作(confirm、decline、seat、complete、no-show)使用 expected_version,而不是幂等键;在得到不明确的响应后,请先读取该预订,再执行其他操作。场所侧取消和散客入座则需要 idempotency_key,与其他键一样,范围限定在您的应用内。

重放事件是幂等的

POST /v1/webhook_events/{eventId}/replay 只会向尚未收到该事件的订阅重新投递。已经收到的订阅会被跳过,因此在故障恢复后重放,不会向正常的端点重复投递。

您这一侧:对投递去重

您必须自行添加幂等性的唯一地方是 webhook 处理程序。投递保证至少一次,因此同一个事件可能多次到达。请根据信封中的 id 去重:
尽可能让处理工作本身也具备幂等性,例如以 Maple 的 order_id 作为您自己订单记录的键,这样重复的 order.notification 会更新记录,而不是产生重复。不要依赖事件顺序;当顺序很重要时,请通过 GET /v1/orders/{orderId} 进行核对。请参阅Webhooks。

总结