Asynchronous Request Processing Capabilities in WRS
WRS allows the asynchronous calling of most endpoints, as prescribed in the
OData Specifications. However, it does not support asynchronous file upload requests.
Asynchronous Request Process
The OData standard facilitates the asynchronous processing of HTTP requests. When a client submits a request, the service immediately returns with a status monitor resource URL. The client can then poll this resource URL to get the response for the submitted request.
Making asynchronous requests ensures that the client can continue execution after initiating the request and process the result whenever the response becomes available.
WRS uses
Windchill Queues for asynchronous processing, in a new dedicated queue called
WRSAsynchProcessingQueue.
The following sequence diagram explains the process:
The client makes a regular WRS request and passes the Prefer: respond-async header to indicate it wishes to receive the response asynchronously. If the server supports asynchronous processing for that request, it will respond with a 202 status code (Accepted) and a Location header in the response. This polling URL, provided in the Location header, is unique and only accessible to the user who created the request.
If the server does not support asynchronous processing, the server will not return an error and the response will be sent synchronously instead. For example, if the request is a file upload request or the Windchill queue responsible for asynchronous processing is stopped, the server will respond synchronously.
The client is expected to keep polling the status monitor URL every 30 seconds until the response is ready (via the Retry-After header).
Per the OData specifications, when the asynchronous processing is complete, the original response will be returned, wrapped into an application/http response with a 200 status code. The response contains a header AsyncResult with the status code of the original response. The response body (of type application/http) will contain the original status code, all original headers and the original response body. For example, if you made an asynchronous POST request that resulted in a 400 Bad Request, the processing will be successful and polling the status monitor URL will return 200. The response AsyncHeader value will be 400 and the response body will contain the original 400 status code and the corresponding error message.
If the status URL returns a status code different from 200 or 202 (typically an error code in the 5xx range), it means the asynchronous processing failed. The client may issue the request again and information about the reasons for failure should be available in the Windchill logs (MethodServer logs or BackgroundMethodServer logs).
To alleviate some of the challenges that could come with parsing an application/http response (especially with file download), a custom header has been introduced. If the client passes PTC-AsyncResponse-ContentType: original when polling the status URL, it will receive the unwrapped, original response (including headers and status code).
| In the case of file download, the server’s response may include redirects. |
Following are a couple of examples.
Example of Successful GET
• Asynchronous Request, with Prefer: respond-async header:
Request:
GET /Windchill/servlet/odata/ProdMgmt/Parts
Prefer: respond-async, odata.maxpagesize=100
Response:
202
Location: https://<Windchill>/Windchill/servlet/odata/status/123456
Preference-Applied: respond-async
• GET status monitor URL
Request:
GET /Windchill/servlet/odata/status/123456
Response:
200
AsyncResult: 200
HTTP/1.1 200 OK
OData-Version: 4.0
Content-Type: application/json;odata.metadata=minimal
Preference-Applied: odata.maxpagesize=100
PTC-Applied-Container-Context: Global
{<the original response JSON> }
Example of POST Request with Error
• Asynchronous Request, with Prefer: respond-async header
Request:
POST /Windchill/servlet/odata/ProdMgmt/Parts
CSRF_NONCE: <NONCE_TOKEN>
Prefer: respond-async
{
“Name”:”AsyncPart”
}
Response:
202
Location: https://<Windchill>/Windchill/servlet/odata/status/456789
Preference-Applied : respond-async
• GET status monitor URL
Request:
GET /Windchill/servlet/odata/status/456789
Response:
200
AsyncResult: 400
HTTP/1.1 400 Bad Request
OData-Version: 4.0
Content-Type: application/json;odata.metadata=minimal
{"error":{"code":"REQUIRED_PROPERTY_MISSING","message":"You must give a value for the following required property: EndItem, AssemblyMode, DefaultUnit, DefaultTraceCode, Source, GatheringPart, PhantomManufacturingPart"}}
Time-to-Live and Delete Mechanism for Asynchronous Responses
As stated above, a client is expected to keep polling the status monitor URL every 30 seconds. If a status monitor URL is not polled for 90 seconds, the system may consider this asynchronous response stale and flag it for deletion. Making a GET request to the status monitor URL refreshes that timeout. As such, it is possible for a client to fetch the asynchronous response multiple times.
Note that the timeout starts after the response has been successfully returned by the server. For example, if it takes 20 minutes to transmit the response to the client, the 90s timeout will only start after those 20 minutes. If the transmission is interrupted, the timeout starts at the time of the interruption. The client is expected to retry within 30 seconds.
By default, stale asynchronous responses are deleted every 10 minutes. This frequency is controlled by the property asynchronousResponseCleanupInterval defined in WT_HOME/codebase/com/ptc/odata/windchill/wrs.properties.xconf. You can adjust it based on your system usage.