Resolve "ICAT registration async"
Closes #3094 (closed)
@demariaa @andy.gotz @wright @bodin @matias.guijarro @meyer
This MR implements asynchronous communication with the ICAT+ REST API.
For example at some point the Bliss code needs the list of datasets in ICAT for the current proposal. Internally it will call this method:
SCAN_SAVING.icat_client.registered_dataset_ids("hc4568", "id11")
In the previous (synchronous) implementation we had a timeout of 2 seconds (by default) and it returned None
when it didn't get a response without 2 seconds.
In the asynchronous implementation we have a timeout of 0.1 seconds (by default) but the actual REST call is made without timeout and keeps running in the background, caching the result when a response from ICAT is received.
When a call times out (which is almost always the case with a 0.1 seconds timeout) it will return the result of the last successful call (or None
when called for the first time).
# process started
>>> print(SCAN_SAVING.icat_client.registered_dataset_ids("hc4568", "id11")) # REST call + wait 0.1 seconds
>>> None
>>> print(SCAN_SAVING.icat_client.registered_dataset_ids("hc4568", "id11")) # wait 0.1 seconds for the call in progress
>>> None
>>> print(SCAN_SAVING.icat_client.registered_dataset_ids("hc4568", "id11")) # wait 0.1 seconds for the call in progress
>>> None
... # the REST call is still running in the background
>>> print(SCAN_SAVING.icat_client.registered_dataset_ids("hc4568", "id11")) # wait 0.1 seconds for the call in progress
>>> [...] # list of datasets
# at this point nothing is running in the background
>>> print(SCAN_SAVING.icat_client.registered_dataset_ids("hc4568", "id11")) # REST call + wait 0.1 seconds
>>> [...] # still the previous result
>>> print(SCAN_SAVING.icat_client.registered_dataset_ids("hc4568", "id11")) # wait 0.1 seconds for the call in progress
>>> [...] # still the previous result
... # the REST call is still running in the background
>>> print(SCAN_SAVING.icat_client.registered_dataset_ids("hc4568", "id11")) # wait 0.1 seconds for the previous call
>>> [...] # the new result
# at this point nothing is running in the background
So a new ICAT+ call is only made when the previous one is finished. You can of course have different calls running in parallel when calling a different method or the same method with different arguments.