Search code examples
restcqrs

RESTful API design with CQRS


I'm aware of this Q/A. The answer doesn't help my situation much.

I'm designing a CQRS-based RESTful service that provides the current reputation of existing accounts. The reputation calculation can take up to 30 seconds.

Due to the long calculation time, and due to our desire to use CQRS on this for other reasons, the entire process is done in two (or more) requests:

FIRST REQUEST

  • A client tells the RESTful service to begin the calculation for the account.
  • The RESTful service basically responds "OK" and has another service start the calculation.

SUBSEQUENT REQUESTS

  • The client asks the RESTful service for the calculated reputation score, if available.
  • The RESTful service responds with either the reputation score, or a note that it's still calculating.

QUESTION #1

How should I structure the first request URI? For account number 12345, should it be something like one of the following?

PUT /accounts/12345   payload: {}

I'm concerned about this approach because I read PUT should be idempotent.

Another option:

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

...or, maybe change the entity from an account to a command...

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

...or something else?


QUESTION #2

For the second request, that seems a bit more straightforward. Should the URI be something like this?

GET /accounts/12345/reputations

I appreciate your suggestions. Thanks.


Solution

  • I may have found an answer. It involves moving the CQRS away from the client, and into the control of the RESTful service, which may employ it optionally.

    For each client request, the URI could be:

    GET /accounts/12345/reputations
    

    Upon receipt, the RESTful service could check to see if a recently-calculated reputation is available. If a recent reputation is available, the RESTful service replies with a 200 OK status and delivers the response payload containing the reputation.

    If no recent reputation is available (nor is it in-process according to the calculating service), the RESTful service kicks into CQRS mode. It tells the calculating service to begin calculating the reputation.

    Then, whether it initiated the calculation, or whether it found one already in process, it returns to the client a 202 Accepted with follow-up link.

    This kind of async situation seems to be what was intended with the 202 Accepted response, per the docs.