我需要 FIFO SQS for jira like board view app

Do I need FIFO SQS for jira like board view app

目前,我在 AWS ECS 上 运行 一个 jira 类板卡管理应用程序,有 8 个任务。当一张卡片从一张 column/stage 移动到另一张时,我会查找该卡片的当前阶段对象,从该阶段移除卡片并将卡片添加到目标阶段对象。到目前为止这是有效的,因为我一直在 Postgres 数据库中寻找实际卡的阶段,而不是基于前端认为该卡属于什么。

问题:

  1. 可以这么说,即使多个用户将同一张卡移动到不同的阶段,但查询仍然会一个接一个地发生,数据不会损坏吗? (例如重复)
  2. 如果数据仍有可能被破坏。使用 SQS FIFO 将消息发送到 lambda 并按顺序处理每个卡片移动是一个不错的选择吗?
  3. 在这种情况下我应该使用 SQS 的任何其他原因?还是 SQS 在这里根本不适用?

虽然您认为 Fifo 队列在这里是最好的是正确的,但我认为您的设计在某些情况下并不理想甚至不可行。

假设用户 1 的应用程序状态是卡处于第 1 阶段,他将其移至第 2 阶段。SQS 消息将指示“将卡从第 1 阶段移至第 2 阶段”。用户 2 具有相同的初始状态,卡 1 处于阶段 1。用户 2 想要将卡移动到阶段 3,因此 SQS 消息将包含“将卡从阶段 1 移动到阶段 3”的指令。但这行不通,因为您再也找不到阶段 1 中的卡片了!

在这个用例中,我认为经典的 API 设计是最好的,其中进行 API 调用以请求移动。在上述情况下,您的 API 应该会出错,表明卡不再处于用户预期的状态。然后应用程序可以重新加载该卡的当前状态并允许用户重试.

这里最重要的问题是:你想要发生什么?

查看数据库中卡片的状态,如果它没有实现您想要的行为,则仅根据该状态采取行动是“错误的”。的确,如果 UI 可能与数据库不同步,那么用户可能不会总能得到他们期望的结果——但仅此而已。

考虑可能性和后果:

  • 两个或更多人将同一张卡同时更新到不同阶段的可能性有多大?
  • 如果他们这样做,后果是什么?

如果一个 20 人的项目团队正在使用这个板,那么我认为机会是 'low/medium',如果他们关注这个板,他们会看到意想不到的变化并且讨论 - 因为显然他们不同意(或者有人不小心把它移到了错误的阶段)。

所以在那种情况下,我认为你没有大问题 - 只要系统行为是你想要的(请参阅下面我的进一步回复)。另一方面,如果您的电路板解决方案用于帮助操作核导弹发射控制系统,那么我认为您的系统不够安全:)

Is it safe to say that even when multiple users move the same card to different stages, but query would still happen one after the other and data will not corrupt? (such as duplicates)

是的,查询仍然会发生 - 假设:

  • 数据库查询根据一些稳定的标识符(例如CardID)查找卡片,并且
  • 成功取回卡后,您的逻辑将其移动到指定的任何目标阶段 - 这意味着没有规则或状态机可能会禁止某些特定的状态转换(例如,从阶段 1 移动到 2 是可以的,但移动从第 2 阶段到第 1 阶段不是)。

关于你的第二个问题:

If there is still a chance data can be corrupted.

这取决于你所说的 'corruption' 是什么意思。数据损坏是指数据发生意外更改,通常使其无法使用(不可处理、不可读等)或无用(可处理但不正确)。在你的情况下,你的系统更有可能正常工作,并且数据不会被破坏(它仍然可以处理,并且数据的结果状态正是系统想要的),但只是结果用户看到的可能不是他们所期望的。

Is it a good option to use SQS FIFO to send message to a lambda and handle each card movement in sequence ?

FIFO 队列只会确保请求按照队列接收请求的顺序进行处理。这是否“好”取决于最重要的问题(此答案的第一句)。

假设我上面提供的假设是正确的:没有强制执行状态机逻辑,并且通过其 ID 找到并处理卡,那么将发生的一切都是最后一个请求将是最终状态。例如:

  • 卡片状态:Card.CardID = 001; Stage = 1.

然后 3 个请求按以下顺序进入 FIFO 队列:

  1. 用户 A - Move CardID 001 to Stage 2.
  2. 用户 B - Move CardID 001 to Stage 4.
  3. 用户 C - Move CardID 001 to Stage 3.

  • 结果卡状态:Card.CardID = 001; Stage = 3

如果您希望最近的请求成为结果,那就“好”了。

Any other reason I should use SQS in this case ? or is SQS not applicable at all here?

我唯一能想到的就是你可以存储一个“历史”,这样用户就可以看到卡片最近的所有变化。这会做两件事:

  • 证明系统正确处理了请求(根据它被告知要做的事情,这是逻辑)。
  • 允许用户查看谁做了什么,并进行讨论。

要实现这一点,您只需按正确的顺序记录卡片的所有相关更改。问题是,数据库可能可以自己做到这一点,所以使用 SQS 仍然值得商榷,队列所能做的就是帮助避免死锁。

更新 - RE 重复卡片

您必须查看 SQS 的文档,看看它是否可以评估队列项目并删除重复项。

假设没有,您将不得不构建一些东西来单独处理它。我现在能想到的就是在将重复项添加到队列之前检查是否有重复项 - 因为一旦存在,可能就太晚了。

一个想法:

  • 在您的代码中建立一个组件作为队列的 proxy/façade。
  • 让它变得聪明,因为它知道最近的卡片操作(“最近”是您认为需要的任何内容)。
  • 一个新的卡片动作来了,它会快速检查是否有任何其他“最近”的重复卡片动作,如果是,则决定要做什么。

一种方法是非常简单的内存中收集,并尽可能快地循环出旧项目。 “最近”,就此集合中项目的生命周期而言,不必与项目通过队列所需的时间相同 - 它只需要足够长的时间让你自己满意,没有明显的重复.

我可以看到这样的设置有效,但可能存在很大问题 - 所以如果你这样做,请尽可能简单。 (“简单”的意思是:功能上尽可能集中)。

  • 尺寸将是一个考虑因素 - 您每分钟处理多少件商品?

  • 操作考虑——如果它在内存中,它很容易丢失(服务重启或其他),所以设计整个系统的方式是,如果那部分出现故障,或者列表已刷新,项目仍会添加到队列中,并且无论如何都会继续工作。