【问题标题】:What should I use as the document key to maintain idempotency?我应该使用什么作为文档密钥来保持幂等性?
【发布时间】:2016-08-30 18:02:51
【问题描述】:

我应该使用什么作为文档键来保持幂等性?

我正在构建一个文本消息应用程序,它使用 CouchDB(客户端上带有 PouchDB)在本地存储消息。 Twilio(SMS 提供者)为每条消息生成一个 ID,我将其用作 CouchDB 文档 ID。这种从 Twilio 的 API 获取消息的方式是幂等的——如果我遇到相同的消息两次,它只会在我的数据库中存储一个副本。

// twilio API /messages
[
  {smsid: 123, body: 'foo'},
  {smsid: 456, body: 'bar'}
]

// transformed into couchdb docs
[
  {id: 123, doc: {_id: 123, body: 'foo'}},
  {id: 456, doc: {_id: 456, body: 'bar'}}
]

当从 twilio 获取消息时,这很容易做到。但是当用户从客户端应用程序发送出站消息时,还没有 twilio ID,因为它还没有被发送到 twilio。

传统方法包括POST将消息发送到我的服务器上的某个端点,然后让服务器将其发送到 twilio,然后在它获得来自 twilio 响应的 smsid 后将记录添加到数据库中。这样做的问题是 (a) 从用户按下“发送”到消息显示在 UI 中存在明显的延迟,并且 (b) 我们无法利用 couchdb 的身份验证系统。

相反,我设置了它,以便客户端生成一个随机 ID,并将其插入数据库(通过 pouchdb w/sync)。然后,服务器监视添加的新出站记录并将它们分派给 twilio。

这种方法效果很好,但是如果我再次GET /messages,它就不再是幂等的了——它会为出站消息创建一个额外的记录,因为我没有以该消息的smsid 作为其键的 couchdb 文档(添加到 couchdb 时没有smsid)。

有没有办法解决这个问题或更好的方法?

【问题讨论】:

  • 除了smsidbody,您还从Twilio 的/messages 获得了哪些其他数据?
  • 我想不出一个简单的解决方案,除非你实现分布式事务。

标签: javascript couchdb twilio


【解决方案1】:

实现这项工作的一个想法是,您必须从每条消息中rely on other data,并忽略 Twilio 的 smsid

也许将用户 ID、消息正文和时间戳的异常版本(例如,int(UNIX-TIMESTAMP-IN-SECONDS/100) 将容忍从您的服务器获取消息到 Twilio 确认它之间存在 100 秒的延迟)。

【讨论】:

  • 嗨 fiatjaf,感谢您在这里提供帮助。我可以给你寄一件 Twilio T 恤来表达我们的感激之情吗?发送电子邮件至 mspeir@twilio.com 了解详情。
  • 谢谢!梅根,我会喜欢的,但在我的国家,如果不向国家支付至少 20 美元(在交货时收取),则不允许 T 恤进入。考虑到这一点,我不得不说不。
【解决方案2】:

感谢您的回复。这是一个艰难的过程。来自 freenode 中#couchdb 的@rnewson 很乐意花一些时间思考这个问题,并提出了一个效果很好的解决方案:

  • couchdb 中的消息文档使用任意_id,可以由服务器或客户端生成
  • 客户端发送消息时,会生成一个任意的_id,并放入数据库中。服务器观察到这一点并将其分派给 twilio,然后通过向文档添加 twilio_id 属性来更新数据库文档
  • 我创建了一个视图来按twilio_id 索引文档
  • 当服务器启动时,它会从 twilio 获取最新消息。为了防止向数据库添加重复记录,它会为每个 twilio id 查询上述视图。对于每个匹配,它使用匹配的_id_rev 执行更新。对于没有匹配的记录,它会生成一个新的任意_id 来执行插入。

对于任何好奇的人,here's the code

再次感谢您的回复!

【讨论】:

    猜你喜欢
    • 2017-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-19
    • 1970-01-01
    • 2012-12-31
    • 2013-07-02
    • 1970-01-01
    相关资源
    最近更新 更多