سؤال

Say you were to develop a REST API that provides access to a set of complex, long-running, operations.

The typical paradigm for an API like this (as I understand it) usually involves (the client) making a request to the server, asking it to perform a given long-running operation. The server will respond with a 202 Accepted message indicating that the request has been received and, with it, provides the location of the result, where it will eventually become available. The client, from then on, polls this location until the result of the long-running task becomes available.

This much makes sense. However, imagine now that these long-running tasks are more complex. Imagine that, during the execution of a task, a specific resource, file, network, etc. becomes unavailable and, in order to proceed, the API must "ask" the client whether the job should continue anyway or whether the task should end here.

How would this requirement change the original paradigm? Instead of having some result located at the given location, would you optionally return some notion of a "question" that needs to be posted back to the server in order to continue?

Assume for the purposes of this question that you can't encode some kind of blanket "continue if error" parameter in the original request and that these questions must be addressed on a case-by-case basis, as they arise, if they arise.

Maybe I'm thinking about this problem the wrong way? I'd be curious to hear how a paradigm like this is usually accomplished, or if it's as simple as, "yeah, just respond with the prompt, post back the result to the server, and continue to query the original location."

I would really appreciate any help I could get.

هل كانت مفيدة؟

المحلول

For long-running operations, it often helps to model the active job as a REST resource with its own structure and/or sub-resources.

For example, starting a job may return a result such as

202 Accepted
Location: https://example.com/jobs/123

At that URL, the client will get a structure such as

{
  "status":"running"
}

as long as the job is running,

{
  "status":"finished",
  "result":"https://example.com/jobs/123/result"
}

when it is completed and a result is available, or

{
  "status":"interaction-required",
  "prompt":"xyz service not available, please restart it or cancel job.",
  "continue":"https://example.com/jobs/123/continue/<token>",
  "cancel":"https://example.com/jobs/123/cancel"
}

to interact with the user. The job would continue (retrying xyz access) after the client posts something to the continue URL (which would include an idempotency token as suggested by @NPSF3000 to prevent accidentally continuing the next interaction), or would be cancelled by posting something to the cancel URL. Another option for cancellation would be a DELETE verb on the job URL. The cancel link could also be made part of the initial job structure to communicate that the job can be cancelled at any time if the application supports that.

The details about which kinds of interaction are possible and how they are presented in the client would need to be designed based on the specific needs of these jobs, but the main thing is that the operation start does not just return the location of the result but of a reified job object that can be queried and manipulated.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى softwareengineering.stackexchange
scroll top