RESTful API 使用 CQRS 进行设计

RESTful API design with CQRS

我知道这个 。答案对我的情况没有多大帮助。

我正在设计一个基于 CQRS 的 RESTful 服务,该服务提供现有帐户的当前信誉。信誉计算最多可能需要 30 秒。

由于计算时间较长,并且由于其他原因我们希望在此上使用CQRS,因此整个过程在两个(或更多)请求中完成:

第一个请求


后续请求


问题 #1

我应该如何构建第一个请求 URI?对于帐号 12345,它应该类似于以下之一吗?

PUT /accounts/12345   payload: {}

我担心这种方法,因为我 read PUT 应该是幂等的。

另一个选项:

POST /accounts/12345   payload: {}   // ...but shouldn't POST contain the whole entity in the payload?

...或者,也许将实体从帐户更改为命令...

POST /command/reputation-calculation/12345  payload: {}  // ...feels like we're getting off-course here

...或其他?


问题 #2

对于第二个请求,这似乎更直接一些。 URI 应该是这样的吗?

GET /accounts/12345/reputations

感谢您的建议。谢谢。

How should I structure the first request URI?

URI 的拼写无关紧要——机器不太关心。如果您考虑通用客户端如何缓存文档,您可能会选择使用 target-uri 专门使缓存中的一个特定资源无效。

使用 POST 很适合 HTTP 缓存的工作方式。此外,这就是我们在 HTML 中的做法,因此您知道它有良好的记录。

因此,如果您 GET /accounts/12345 查看当前的信誉分数,那么 POST /accounts/12345 是启动升级过程的完全合理的方式。

如果您使用的是超媒体(这是 REST 约束之一),那么您从 POST 获得的响应将包含状态监视器的 URI。所以 URI 可以是任何你想要的(因为客户端只是去你告诉它的地方)。服务器可能希望得到提示以了解您正在询问哪个更新;所以它可能是 GET /reputationUpdate/67890.

将状态监视器与帐户放在同一层次结构中可能会有优势,因此 GET /accounts/12345/reputationUpdate/67890 也可以。

web linking specification 一致的拼写通常使客户端或服务器的实施更容易,因为您可以获取理解模板的现成库。

我可能已经找到答案了。它涉及将 CQRS 从客户端移开,并置于 RESTful 服务的控制之下,该服务可以选择使用它。

对于每个客户端请求,URI 可以是:

GET /accounts/12345/reputations

收到后,RESTful 服务可以检查 recently-calculated 信誉是否可用。如果最近的信誉可用,RESTful 服务会回复 200 OK 状态并传送包含信誉的响应负载。

如果没有最近的信誉可用(根据计算服务也不是 in-process),RESTful 服务将进入 CQRS 模式。它告诉计算服务开始计算信誉。

然后,无论是开始计算,还是发现计算已经在进行中,它都会 returns 向客户端 202 Accepted 和 follow-up link。

根据 docs.

,这种异步情况似乎是 202 Accepted 响应的目的

REST 不太适合 CQRS command-oriented 系统。因此,如果客户端是 command-oriented,则只需使用 HTTP 作为传输方式。

或者,客户端可以创建状态为 calculatingreadyreputation-enquiry 资源。 back-end 决定是否可以重复使用最近的计算结果,在这种情况下,状态将立即变为 ready。当资源为 ready.

时提供 score