此 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 即可。
expected_version 被检查,因为在原始写入成功后,expected_version 往往已经过期。
原生和第三方服务商的保留(hold)都会被持久化,并归获取它们的应用所有。重复提交同一个 slot_token 会重放该应用仍有效的保留,而不会再占用新的锁。其他应用无法使用或释放它,即使在共同授权的门店也是如此。未知的服务商保留在经过保守的 24 小时不活动隔离期后,会释放其配额预留,这与其保留的审计记录无关;已过期的操作无法通过重试恢复。
由第三方服务商支持的写入
对于 OpenTable,Maple 会在向服务商发起 I/O 之前,持久地占用该键和请求摘要,并使用同一个稳定的服务商请求 ID。待处理的更改或取消还会为镜像预订预留,以防其他合作伙伴写入。成功后,Maple 会同时记录镜像和重放结果。暂时性的镜像失败会同步重试;后台对账程序会修复未完成的工作。 服务商超时会在结果尚未确定时返回409 operation_in_progress。请在 details.retry_after 秒后,使用相同的请求和键重试。在使用原始服务商请求 ID 重复执行预订写入之前,Maple 会先执行一次对账读取。已完成的写入会直接重放,不会再次调用服务商。
预订配置则改用内容寻址的发布方式:相同的配置无需显式的键,也不会产生任何变化。状态类场所操作(confirm、decline、seat、complete、no-show)使用 expected_version,而不是幂等键;在得到不明确的响应后,请先读取该预订,再执行其他操作。场所侧取消和散客入座则需要 idempotency_key,与其他键一样,范围限定在您的应用内。
重放事件是幂等的
POST /v1/webhook_events/{eventId}/replay 只会向尚未收到该事件的订阅重新投递。已经收到的订阅会被跳过,因此在故障恢复后重放,不会向正常的端点重复投递。
您这一侧:对投递去重
您必须自行添加幂等性的唯一地方是 webhook 处理程序。投递保证至少一次,因此同一个事件可能多次到达。请根据信封中的id 去重:
order_id 作为您自己订单记录的键,这样重复的 order.notification 会更新记录,而不是产生重复。不要依赖事件顺序;当顺序很重要时,请通过 GET /v1/orders/{orderId} 进行核对。请参阅Webhooks。