Asynchronous Commands

Methods whose names end with Async are asynchronous commands. These commands are sent to the server as a request and queued for processing. Asynchronous methods return Request Structure. Use getRequestStatus() and getRequestResult() to monitor the status of a request.

RequestId

All asynchronous methods from the JetStream API return a Request Structure containing requestId. Because of their asynchronous nature, such methods cannot return any meaningful data. You must use the returned structure or the requestId to monitor the status of the request, and to retrieve its result.

>>> request = api.send.setSendRateAsync(...)
{'requestId': 17}
>>> requestId = request['requestId']
17

Using A RequestId

The JetStream API provides two methods that operate on requestId:

  1. getRequestStatus() will return the status of the request, indicating whether it is still being processed by the server. This method returns immediately.
  2. getRequestResult() will wait until the request is completed and return its result. This method blocks until the result is available.

These two methods are available from ServerInterface class.

Example:
>>> status = api.server.getRequestStatus(requestId)
{'requestId': 17, 'processing': False}
>>> result = api.server.getRequestResult(requestId)
{'blockSize': 256,
'blocksAcked': 0,
'blocksSent': 0,
'bytesRecv': 0,
'bytesSent': 0,
'destinationId': 'receiver01:8886',
'endTime': None,
'errorMessage': '',
'packetsRecv': 0,
'packetsSent': 0,
'processing': True,
'queueTime': None,
'requestTime': 1477934856594315,
'snapshotTime': 1477934856594318,
'startTime': None,
'status': 'pending',
'totalBlocks': 3354311,
'totalBytes': 858703405,
'transferId': 7}

It is not required that you monitor a request, nor that you retrieve its result. The request will be fulfilled without your intervention.

Expiry Of A RequestId

In order to allow you to retrieve the results from an asynchronous method, it is necessary that the server maintain a record of its asynchronous requests, as well as a copy of the result it produced. It is not feasible for the server to maintain this association indefinitely, as the server would eventually run out of resources. For this reason, asynchronous requests will eventually expire. After it expires, its result will no longer be available, and calls to getRequestStatus and getRequestResult using the expired requestId will fail. A requestId is never reused.

Example:
>>> status = api.server.getRequestStatus(requestId)
{'requestId': 17, 'processing': False}

(time passes…)

>>> status = api.server.getRequestStatus(requestId)
# CommandException: No request with specified ID.

Asynchronous Requests vs Ongoing Tasks

The commands createManifest() and createTransfer() are unique in the fact that they initiate a task on the server which may not be complete at the point where the command returns. The server handles these operations differently than others, and for this reason these methods do not use the “Async” naming scheme. Clients using the JetStream API will need to be aware of this, and be prepared to handle manifest and transfer results differently than other results.

Commands such as setSendRateAsync() and suspendTransferAsync() are asynchronous requests. They do not return a result. Instead, they return a Request Structure which must be submitted to the API to retrieve the result.

Examples:
>>> requestId = api.send.setSendRateAsync(...)
{'requestId': 3}
>>> result = api.server.getRequestResult(requestId)
{'sendRate': 12345.0}
>>> requestId = api.send.suspendTransferAsync(...)
{'requestId': 13}
>>> result = api.server.getRequestResult(requestId)
{'transferId': '00f74049d7201b46020000000000000d'}

In the examples above, setSendRateAsync and suspendTransferAsync each add a request to the server’s request queue. When getRequestResult() is called the API will block until the server has processed the request associated with the requestId, and will return the command’s result.

To compare, createManifest() and createTransfer() are synchronous, and each returns a result. The createManifest() command returns a Manifest Structure, and the createTransfer() command returns a Transfer Structure.

Examples:
>>> manifest = api.send.createManifest(...)
{'errorMessage': None,
 'manifestId': '00f74049d7201b460100000000000000',
 'processing': True,
 'status': 'pending',
 'totalFiles': None,
 'totalSize': None}
>>> transfer = api.send.createTransfer(...)
{'manifestId': '00f74049d7201b460100000000000008',
 'packetsRecv': 0,
 'packetsSent': 0,
 'priority': 100,
 'processing': True,
 'queueTime': None,
 'requestTime': 1494285094171160,
 'snapshotTime': 1494285094171177,
 'startTime': None,
 'status': 'pending',
 'transferId': '00f74049d7201b460200000000000009'}

However, these structures both describe an ongoing task. The distinction lies in how manifests and transfers are managed by the server. For clients of the API, what’s important is that waiting for the completion of a manifest or transfer is performed via waitForManifest() and waitForTransfer(), respectively.

Examples:
>>> manifest = api.send.waitForManifest(manifest)
{'errorMessage': None,
 'manifestId': '00f74049d7201b460100000000000000',
 'processing': False,
 'status': 'complete',
 'totalFiles': 617,
 'totalSize': 11963203587}
>>> transfer = api.send.waitForTransfer(transfer)
{'manifestId': '00f74049d7201b460100000000000008',
 'packetsRecv': 12,
 'packetsSent': 20682,
 'priority': 100,
 'processing': False,
 'queueTime': 1494285094171217,
 'requestTime': 1494285094171160,
 'snapshotTime': 1494285107174540,
 'startTime': 1494285094171421,
 'status': 'complete',
 'transferId': '00f74049d7201b460200000000000009'}