daq-queuing-service 0.2.0__tar.gz → 0.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/PKG-INFO +1 -1
  2. daq_queuing_service-0.2.2/docs/explanations/beamlines/i15-1/auxiliary_scans.md +25 -0
  3. daq_queuing_service-0.2.2/docs/explanations/beamlines/i15-1/i15-1.md +8 -0
  4. daq_queuing_service-0.2.2/docs/explanations/beamlines/i15-1/i15-1_aux_scans.drawio.png +0 -0
  5. daq_queuing_service-0.2.2/docs/explanations/beamlines.md +8 -0
  6. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/docs/reference/rest_api.json +3 -22
  7. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/_version.py +3 -3
  8. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/external_interaction/tiled/tiled.py +11 -8
  9. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/plugins/i15_1/auxiliary.py +38 -3
  10. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/plugins/i15_1/i15_1_converter.py +88 -42
  11. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/plugins/i15_1/tiled_interaction.py +9 -2
  12. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/task_queue/queue.py +12 -4
  13. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service.egg-info/PKG-INFO +1 -1
  14. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service.egg-info/SOURCES.txt +4 -1
  15. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service.egg-info/scm_file_list.json +4 -1
  16. daq_queuing_service-0.2.2/src/daq_queuing_service.egg-info/scm_version.json +8 -0
  17. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/unit_tests/external_interaction/tiled/test_tiled.py +16 -18
  18. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/unit_tests/plugins/i15_1/test_auxiliary.py +159 -1
  19. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/unit_tests/plugins/i15_1/test_i15_1_converter.py +174 -39
  20. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/unit_tests/plugins/i15_1/test_tiled_interaction.py +93 -27
  21. daq_queuing_service-0.2.0/docs/explanations/beamlines/i15-1/backgrounds_logic.drawio.png +0 -0
  22. daq_queuing_service-0.2.0/src/daq_queuing_service.egg-info/scm_version.json +0 -8
  23. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/.copier-answers.yml +0 -0
  24. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/.devcontainer/devcontainer.json +0 -0
  25. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/.github/CONTRIBUTING.md +0 -0
  26. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  27. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/.github/ISSUE_TEMPLATE/issue.md +0 -0
  28. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +0 -0
  29. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/.github/pages/index.html +0 -0
  30. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/.github/pages/make_switcher.py +0 -0
  31. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/.github/workflows/_container.yml +0 -0
  32. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/.github/workflows/_dist.yml +0 -0
  33. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/.github/workflows/_docs.yml +0 -0
  34. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/.github/workflows/_pypi.yml +0 -0
  35. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/.github/workflows/_release.yml +0 -0
  36. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/.github/workflows/_test.yml +0 -0
  37. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/.github/workflows/_tox.yml +0 -0
  38. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/.github/workflows/ci.yml +0 -0
  39. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/.github/workflows/periodic.yml +0 -0
  40. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/.gitignore +0 -0
  41. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/.gitleaks.toml +0 -0
  42. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/.pre-commit-config.yaml +0 -0
  43. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/.python-version +0 -0
  44. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/.vscode/extensions.json +0 -0
  45. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/.vscode/launch.json +0 -0
  46. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/.vscode/settings.json +0 -0
  47. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/.vscode/tasks.json +0 -0
  48. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/Dockerfile +0 -0
  49. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/LICENSE +0 -0
  50. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/README.md +0 -0
  51. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/catalog-info.yaml +0 -0
  52. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/docs/_api.rst +0 -0
  53. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/docs/_templates/custom-module-template.rst +0 -0
  54. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/docs/conf.py +0 -0
  55. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/docs/explanations/converters.md +0 -0
  56. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/docs/explanations/decisions/0001-record-architecture-decisions.md +0 -0
  57. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/docs/explanations/decisions/0002-switched-to-python-copier-template.md +0 -0
  58. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/docs/explanations/decisions/COPYME +0 -0
  59. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/docs/explanations/decisions.md +0 -0
  60. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/docs/explanations/queue.md +0 -0
  61. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/docs/explanations/worker.md +0 -0
  62. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/docs/explanations.md +0 -0
  63. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/docs/genindex.md +0 -0
  64. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/docs/how-to/contribute.md +0 -0
  65. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/docs/how-to/notify-to-slack.md +0 -0
  66. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/docs/how-to/run-container.md +0 -0
  67. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/docs/how-to.md +0 -0
  68. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/docs/images/dls-logo.svg +0 -0
  69. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/docs/images/worker_logic.drawio.png +0 -0
  70. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/docs/index.md +0 -0
  71. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/docs/reference/log.rst +0 -0
  72. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/docs/reference/queue-plugin.rst +0 -0
  73. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/docs/reference/queue.rst +0 -0
  74. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/docs/reference/reference.md +0 -0
  75. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/docs/reference/rest-api.rst +0 -0
  76. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/docs/reference.md +0 -0
  77. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/docs/tutorials/installation.md +0 -0
  78. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/docs/tutorials.md +0 -0
  79. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/helm/daq-queuing-service/.helmignore +0 -0
  80. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/helm/daq-queuing-service/Chart.yaml +0 -0
  81. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/helm/daq-queuing-service/templates/_helpers.tpl +0 -0
  82. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/helm/daq-queuing-service/templates/configmap.yaml +0 -0
  83. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/helm/daq-queuing-service/templates/deployment.yaml +0 -0
  84. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/helm/daq-queuing-service/templates/ingress.yaml +0 -0
  85. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/helm/daq-queuing-service/templates/service.yaml +0 -0
  86. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/helm/daq-queuing-service/values.yaml +0 -0
  87. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/pyproject.toml +0 -0
  88. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/renovate.json +0 -0
  89. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/setup.cfg +0 -0
  90. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/__init__.py +0 -0
  91. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/__main__.py +0 -0
  92. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/api/__init__.py +0 -0
  93. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/api/api.py +0 -0
  94. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/api/errors.py +0 -0
  95. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/app/__init__.py +0 -0
  96. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/app/app.py +0 -0
  97. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/app/authentication.py +0 -0
  98. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/app/authorisation.py +0 -0
  99. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/app/config.py +0 -0
  100. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/broadcaster.py +0 -0
  101. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/external_interaction/__init__.py +0 -0
  102. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/external_interaction/blueapi/__init__.py +0 -0
  103. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/external_interaction/blueapi/blueapi_adapter.py +0 -0
  104. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/external_interaction/blueapi/blueapi_call.py +0 -0
  105. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/external_interaction/blueapi/get_client.py +0 -0
  106. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/external_interaction/blueapi/token_source.py +0 -0
  107. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/external_interaction/runtime_estimator/client.py +0 -0
  108. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/external_interaction/tiled/__init__.py +0 -0
  109. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/log.py +0 -0
  110. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/plugins/converter.py +0 -0
  111. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/plugins/i15_1/plans.py +0 -0
  112. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/task_queue/__init__.py +0 -0
  113. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/task_queue/queue_utils.py +0 -0
  114. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/task_queue/task.py +0 -0
  115. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/worker/__init__.py +0 -0
  116. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service/worker/worker.py +0 -0
  117. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service.egg-info/dependency_links.txt +0 -0
  118. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service.egg-info/entry_points.txt +0 -0
  119. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service.egg-info/requires.txt +0 -0
  120. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/src/daq_queuing_service.egg-info/top_level.txt +0 -0
  121. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/conftest.py +0 -0
  122. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/constants.py +0 -0
  123. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/system_tests/compose.yaml +0 -0
  124. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/system_tests/config_with_auth.yaml +0 -0
  125. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/system_tests/services/rabbitmq_plugins +0 -0
  126. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/test_data/i15_1/test_blueapi_config.yaml +0 -0
  127. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/test_data/i15_1/test_daq_queue_config.yaml +0 -0
  128. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/test_data/test_blueapi_config.yaml +0 -0
  129. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/test_data/test_config.yaml +0 -0
  130. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/test_data/test_config_with_auth.yaml +0 -0
  131. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/unit_tests/__init__.py +0 -0
  132. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/unit_tests/conftest.py +0 -0
  133. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/unit_tests/external_interaction/blueapi/test_blueapi_adapter.py +0 -0
  134. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/unit_tests/external_interaction/blueapi/test_blueapi_call.py +0 -0
  135. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/unit_tests/external_interaction/blueapi/test_get_blueapi_client.py +0 -0
  136. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/unit_tests/external_interaction/runtime_estimator/test_client.py +0 -0
  137. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/unit_tests/plugins/__init__.py +0 -0
  138. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/unit_tests/plugins/i15_1/__init__.py +0 -0
  139. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/unit_tests/plugins/i15_1/conftest.py +0 -0
  140. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/unit_tests/plugins/test_converter.py +0 -0
  141. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/unit_tests/test_api.py +0 -0
  142. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/unit_tests/test_app.py +0 -0
  143. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/unit_tests/test_authentication.py +0 -0
  144. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/unit_tests/test_authorisation.py +0 -0
  145. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/unit_tests/test_broadcaster.py +0 -0
  146. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/unit_tests/test_cli.py +0 -0
  147. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/unit_tests/test_log.py +0 -0
  148. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/unit_tests/test_queue.py +0 -0
  149. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/unit_tests/test_task.py +0 -0
  150. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/unit_tests/test_udc_token_source.py +0 -0
  151. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/tests/unit_tests/test_worker.py +0 -0
  152. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/utility_scripts/generate_api_docs.py +0 -0
  153. {daq_queuing_service-0.2.0 → daq_queuing_service-0.2.2}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: daq-queuing-service
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: A service to queue tasks and chain BlueAPI calls
5
5
  Author-email: Jacob Williamson <jacob.williamson@diamond.ac.uk>
6
6
  License: Apache License
@@ -0,0 +1,25 @@
1
+ # i15-1 Auxiliary Scans
2
+
3
+ I15-1 PDF experiments require some scans to be run before hand, for use during analysis. These are added to the queue automatically by the i15-1 queue plugin. For each experiment, we need:
4
+
5
+ - an air scan, at room temperature
6
+ - an empty capillary scan, matching the capillary type and temperature range to the experiment
7
+ - a standard sample scan, at room temperature, matching the capillary type to the experiment
8
+
9
+ These must happen in this order, as the analysis process is layered - i.e, the empty capillary scan needs the air scan to be processed, the standard sample needs the empty capillary, and therefore the air, and the actual experiment needs all three. Additionally, to save time, we can merge these auxiliary scans together, to avoid queuing up three additional scans for every experiment. For example, experiments can always share an air scan (as it's always the same); empty capillary scans can be shared as long as the temperature range spans the range of the experiment, and the capillary type is the same; and standard sample scans can be shared as long as the capillary type is the same.
10
+
11
+ The above requirements lead to the following logic:
12
+
13
+ - An experiment will require the three auxiliary scans outlined above, the details of which will be a function of the experiment parameters. See `I151Converter._get_required_auxiliary_scans`
14
+ - An `AuxiliaryScan` has a `requires` field, which details the other required auxiliary scans that must proceed it. The `AuxiliaryScan` objects produced by `I151Converter._get_required_auxiliary_scans` have each other as requirements. The empty capillary scan will be required by the standard sample scan, and the air scan will be required by both the other two.
15
+
16
+ To add auxiliary scans, we build a new queue that includes the tasks along with their auxiliary scans. For each task in the queue, we will:
17
+
18
+ - Gather the required auxiliary scans
19
+ - For each required auxiliary scan:
20
+ - Check whether a matching auxiliary scan already exists in the queue or tiled. For an existing scan to be considered suitable, all of the required auxiliary scan's own required auxiliary scans must also be required by the existing scan.
21
+ - If a suitable existing does not exist, we will see if we can combine the required auxiliary scan with an existing scan. This, for example, could involve expanding the temperature range of a queued auxiliary scan. Combining these auxiliary scans also combines the requirements of both scans, so no requirement information is lost, but we also don't duplicate similar requirements. We then go to the beginning of this checklist, and repeat for the required auxiliary scans of the combined auxiliary scan, inserting the results before the combined scan in the queue.
22
+ - If we cannot combine the required auxiliary scan, we will add the auxiliary scan to the queue. However, right before we do this, we will go through the required auxiliary scans of the auxiliary scan we added, and repeat this checklist for them. This ensures the auxiliary scan is added behind its requirements.
23
+ - Once all the recursive adding of required auxiliary scans is complete, we add the task itself to the new queue.
24
+
25
+ ![Auxiliary scan logic flowchart](./i15-1_aux_scans.drawio.png)
@@ -0,0 +1,8 @@
1
+ # i15-1
2
+
3
+ ```{toctree}
4
+ :maxdepth: 1
5
+ :glob:
6
+
7
+ Auxiliary Scans <auxiliary_scans>
8
+ ```
@@ -0,0 +1,8 @@
1
+ # Beamlines
2
+
3
+ ```{toctree}
4
+ :maxdepth: 1
5
+ :glob:
6
+
7
+ i15-1 <beamlines/i15-1/i15-1>
8
+ ```
@@ -1072,29 +1072,9 @@
1072
1072
  "OIDCConfig": {
1073
1073
  "properties": {
1074
1074
  "well_known_url": {
1075
- "anyOf": [
1076
- {
1077
- "type": "string"
1078
- },
1079
- {
1080
- "type": "null"
1081
- }
1082
- ],
1075
+ "type": "string",
1083
1076
  "title": "Well Known Url",
1084
- "description": "URL to fetch OIDC config from the provider",
1085
- "deprecated": true
1086
- },
1087
- "issuer": {
1088
- "anyOf": [
1089
- {
1090
- "type": "string"
1091
- },
1092
- {
1093
- "type": "null"
1094
- }
1095
- ],
1096
- "title": "Issuer",
1097
- "description": "URL of OIDC provider"
1077
+ "description": "URL to fetch OIDC config from the provider"
1098
1078
  },
1099
1079
  "client_id": {
1100
1080
  "type": "string",
@@ -1117,6 +1097,7 @@
1117
1097
  "additionalProperties": false,
1118
1098
  "type": "object",
1119
1099
  "required": [
1100
+ "well_known_url",
1120
1101
  "client_id"
1121
1102
  ],
1122
1103
  "title": "OIDCConfig"
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '0.2.0'
22
- __version_tuple__ = version_tuple = (0, 2, 0)
21
+ __version__ = version = '0.2.2'
22
+ __version_tuple__ = version_tuple = (0, 2, 2)
23
23
 
24
- __commit_id__ = commit_id = 'g12403b775'
24
+ __commit_id__ = commit_id = 'gfddbbda69'
@@ -55,16 +55,19 @@ def get_tiled_client(
55
55
 
56
56
 
57
57
  def get_metadata_from_tiled(
58
- tiled_client: Container, instrument_session: str, blueapi_task_id: str
58
+ tiled_client: Container,
59
+ instrument: str,
60
+ instrument_session: str,
61
+ blueapi_task_id: str,
59
62
  ) -> list[tuple[str, dict[str, Any]]]:
60
63
 
61
64
  @cached(cache)
62
65
  def _query_tiled(
63
- instrument_session: str, blueapi_task_id: str
66
+ instrument: str, instrument_session: str, blueapi_task_id: str
64
67
  ) -> list[tuple[str, dict[str, Any]]]:
65
- result: Container = tiled_client.search(
66
- Eq("start.instrument_session", instrument_session)
67
- ).search(Eq("start.blueapi_task_id", blueapi_task_id))
68
+ result: Container = tiled_client[
69
+ f"{instrument}/{instrument_session.split('-')[0]}/{instrument_session}"
70
+ ].search(Eq("start.blueapi_task_id", blueapi_task_id))
68
71
 
69
72
  items = sorted(
70
73
  ((key, dict(value.metadata)) for key, value in result.items()),
@@ -72,10 +75,10 @@ def get_metadata_from_tiled(
72
75
  )
73
76
  return items
74
77
 
75
- return _query_tiled(instrument_session, blueapi_task_id)
78
+ return _query_tiled(instrument, instrument_session, blueapi_task_id)
76
79
 
77
80
 
78
- def get_tiled_and_scan_ids(tiled_client: Container, call: BlueapiCall):
81
+ def get_tiled_and_scan_ids(tiled_client: Container, instrument: str, call: BlueapiCall):
79
82
  tiled_ids: list[str] = []
80
83
  scan_ids: list[int] = []
81
84
 
@@ -84,7 +87,7 @@ def get_tiled_and_scan_ids(tiled_client: Container, call: BlueapiCall):
84
87
  return tiled_ids, scan_ids
85
88
 
86
89
  scan_metadatas = get_metadata_from_tiled(
87
- tiled_client, call.task_request.instrument_session, call.blueapi_id
90
+ tiled_client, instrument, call.task_request.instrument_session, call.blueapi_id
88
91
  )
89
92
 
90
93
  for item in scan_metadatas:
@@ -1,8 +1,10 @@
1
+ from collections.abc import Sequence
1
2
  from enum import StrEnum
2
3
  from pathlib import Path
4
+ from typing import Self
3
5
 
4
6
  from daq_config_server.models.i15_1.standards_puck import StandardsPin
5
- from pydantic import BaseModel, ConfigDict, computed_field
7
+ from pydantic import BaseModel, ConfigDict, Field, computed_field
6
8
 
7
9
  from daq_queuing_service.task_queue.task import Experiment
8
10
 
@@ -32,6 +34,25 @@ def get_background_temperatures(
32
34
  )
33
35
 
34
36
 
37
+ def combine_auxiliary_requirements(
38
+ required_auxiliaries_1: Sequence["AuxiliaryScan"],
39
+ required_auxiliaries_2: list["AuxiliaryScan"],
40
+ ) -> list["AuxiliaryScan"]:
41
+ result: list[AuxiliaryScan] = []
42
+ remaining = required_auxiliaries_2.copy()
43
+ for aux1 in required_auxiliaries_1:
44
+ for aux2 in remaining:
45
+ if combined := aux1.attempt_to_combine_with(aux2):
46
+ result.append(combined)
47
+ remaining.remove(aux2)
48
+
49
+ break
50
+ else:
51
+ result.append(aux1)
52
+
53
+ return result + remaining
54
+
55
+
35
56
  class AuxiliaryScan(BaseModel):
36
57
  """Auxiliary scans are scans added automatically by the queue, such as background
37
58
  scans and standard sample calibration scans. They are needed for analysis of user
@@ -43,6 +64,7 @@ class AuxiliaryScan(BaseModel):
43
64
  pin: StandardsPin | None
44
65
  time_per_pdf: float
45
66
  list_of_temperatures: list[int] | None = None
67
+ requires: list[Self] = Field(default_factory=lambda: [])
46
68
 
47
69
  @computed_field
48
70
  @property
@@ -59,7 +81,9 @@ class AuxiliaryScan(BaseModel):
59
81
  temperature_step: int = DEFAULT_TEMPERATURE_STEP,
60
82
  ) -> bool:
61
83
  """Determine if this background is suitable compared to an experiment's required
62
- background.
84
+ background. This includes checking that scans in required_background.requires
85
+ have a suitable pairing in self.requires, to ensure nested requirements are
86
+ taken into account.
63
87
 
64
88
  Args:
65
89
  required_background (AuxiliaryScan): The required background
@@ -75,6 +99,10 @@ class AuxiliaryScan(BaseModel):
75
99
  elif self.list_of_temperatures:
76
100
  return False
77
101
 
102
+ for required in required_background.requires:
103
+ if not any(r.is_suitable(required) for r in self.requires):
104
+ return False
105
+
78
106
  return (
79
107
  self.instrument_session == required_background.instrument_session
80
108
  and self.pin == required_background.pin
@@ -109,7 +137,8 @@ class AuxiliaryScan(BaseModel):
109
137
  temperature_step: int = DEFAULT_TEMPERATURE_STEP,
110
138
  ) -> "AuxiliaryScan | None":
111
139
  """Creates a background that combines the requirements of this background object
112
- and a provided required background, if possible.
140
+ and a provided required background, if possible. Anything that previously deemed
141
+ this scan as suitable should also deem the combined scan suitable.
113
142
 
114
143
  Args:
115
144
  required_background (AuxiliaryScan): The required background
@@ -142,6 +171,9 @@ class AuxiliaryScan(BaseModel):
142
171
  pin=self.pin,
143
172
  time_per_pdf=max(self.time_per_pdf, required_background.time_per_pdf),
144
173
  list_of_temperatures=list_of_temperatures,
174
+ requires=combine_auxiliary_requirements(
175
+ self.requires, required_background.requires
176
+ ),
145
177
  )
146
178
  assert result.is_suitable(required_background)
147
179
  return result
@@ -167,6 +199,9 @@ class AuxiliaryScan(BaseModel):
167
199
  list_of_temperatures=experiment.experiment_definition.data.get(
168
200
  "list_of_temperatures"
169
201
  ),
202
+ requires=experiment.experiment_definition.data.get(
203
+ "required_auxiliary_scans", []
204
+ ),
170
205
  )
171
206
 
172
207
 
@@ -1,3 +1,4 @@
1
+ from dataclasses import dataclass, replace
1
2
  from functools import cached_property
2
3
  from typing import Any
3
4
 
@@ -52,9 +53,16 @@ QUEUE_PARAMS_CONFIG_PATH = (
52
53
  )
53
54
 
54
55
 
55
- def _filter_auxiliary_scans(tasks: list[Task]) -> list[tuple[int, AuxiliaryScan]]:
56
+ @dataclass(frozen=True)
57
+ class QueuedAuxiliary:
58
+ index: int
59
+ task_id: str
60
+ auxiliary: AuxiliaryScan
61
+
62
+
63
+ def _filter_auxiliary_scans(tasks: list[Task]) -> list[QueuedAuxiliary]:
56
64
  return [
57
- (i, AuxiliaryScan.from_experiment(task.experiment))
65
+ QueuedAuxiliary(i, task.id, AuxiliaryScan.from_experiment(task.experiment))
58
66
  for i, task in enumerate(tasks)
59
67
  if isinstance(task.experiment, Experiment)
60
68
  and is_auxiliary_experiment(task.experiment)
@@ -200,9 +208,7 @@ class I151Converter(Converter):
200
208
  for task in tasks:
201
209
  with add_session_to_logger(task.experiment.instrument_session):
202
210
  experiment = task.experiment
203
- if isinstance(experiment, Experiment) and not is_auxiliary_experiment(
204
- experiment
205
- ):
211
+ if isinstance(experiment, Experiment):
206
212
  instrument_session = experiment.instrument_session
207
213
 
208
214
  required_auxiliary_scans = self._get_required_auxiliary_scans(
@@ -241,8 +247,8 @@ class I151Converter(Converter):
241
247
 
242
248
  queued_auxiliary_scans = _filter_auxiliary_scans(new_tasks)
243
249
  if any(
244
- queued_auxiliary.is_suitable(required_auxiliary)
245
- for _, queued_auxiliary in queued_auxiliary_scans
250
+ queued_auxiliary.auxiliary.is_suitable(required_auxiliary)
251
+ for queued_auxiliary in queued_auxiliary_scans
246
252
  ):
247
253
  return new_tasks
248
254
 
@@ -260,6 +266,7 @@ class I151Converter(Converter):
260
266
  )
261
267
  return self._add_or_replace_auxiliary_scan(
262
268
  required_auxiliary,
269
+ current_task,
263
270
  new_tasks,
264
271
  queued_auxiliary_scans,
265
272
  instrument_session,
@@ -268,32 +275,65 @@ class I151Converter(Converter):
268
275
  def _add_or_replace_auxiliary_scan(
269
276
  self,
270
277
  required_auxiliary: AuxiliaryScan,
278
+ current_task: TaskWithPosition | None,
271
279
  new_tasks: list[Task],
272
- queued_auxiliary_scans: list[tuple[int, AuxiliaryScan]],
280
+ queued_auxiliary_scans: list[QueuedAuxiliary],
273
281
  instrument_session: str,
274
282
  ) -> list[Task]:
275
- combined_auxiliary_scan = None
276
- index = None
277
-
278
- for i, auxiliary_scan in queued_auxiliary_scans:
279
- if combined_auxiliary_scan := auxiliary_scan.attempt_to_combine_with(
280
- required_auxiliary
281
- ):
282
- index = i
283
- break
283
+ # It is assumed every scan in queued_auxiliary_scans has already added their
284
+ # requirements before for them
285
+ combined_auxiliary = self._find_combinable_auxiliary(
286
+ required_auxiliary, queued_auxiliary_scans
287
+ )
284
288
 
285
289
  aux_experiment = self._construct_auxiliary_experiment(
286
- combined_auxiliary_scan or required_auxiliary, instrument_session
290
+ combined_auxiliary.auxiliary if combined_auxiliary else required_auxiliary,
291
+ instrument_session,
287
292
  )
288
- if index is None:
289
- new_tasks.append(Task(experiment=aux_experiment))
293
+
294
+ if combined_auxiliary is None:
295
+ aux_task = Task(experiment=aux_experiment)
296
+ prefix = new_tasks
297
+ suffix = []
298
+ additional_required = required_auxiliary.requires
290
299
  else:
291
- new_tasks[index] = Task(experiment=aux_experiment)
300
+ aux_task = Task(experiment=aux_experiment, id=combined_auxiliary.task_id)
301
+ prefix = new_tasks[: combined_auxiliary.index]
302
+ suffix = new_tasks[combined_auxiliary.index + 1 :]
303
+ additional_required = combined_auxiliary.auxiliary.requires
304
+
305
+ for required in additional_required:
306
+ prefix = self._ensure_auxiliary_in_queue_or_tiled(
307
+ required,
308
+ current_task,
309
+ prefix,
310
+ aux_task.id,
311
+ instrument_session,
312
+ )
313
+ new_tasks = prefix + [aux_task] + suffix
314
+
292
315
  return new_tasks
293
316
 
317
+ def _find_combinable_auxiliary(
318
+ self,
319
+ required_auxiliary: AuxiliaryScan,
320
+ queued_auxiliary_scans: list[QueuedAuxiliary],
321
+ ):
322
+ for queued_auxiliary in queued_auxiliary_scans:
323
+ if (
324
+ combined_auxiliary_scan
325
+ := queued_auxiliary.auxiliary.attempt_to_combine_with(
326
+ required_auxiliary
327
+ )
328
+ ):
329
+ return replace(queued_auxiliary, auxiliary=combined_auxiliary_scan)
330
+
294
331
  def _get_required_auxiliary_scans(
295
332
  self, experiment: Experiment
296
333
  ) -> list[AuxiliaryScan]:
334
+ if is_auxiliary_experiment(experiment):
335
+ return experiment.experiment_definition.data["required_auxiliary_scans"]
336
+
297
337
  time_per_pdf = experiment.experiment_definition.data["time_per_pdf"]
298
338
  list_of_temperatures = experiment.experiment_definition.data.get(
299
339
  "list_of_temperatures"
@@ -302,34 +342,40 @@ class I151Converter(Converter):
302
342
  list_of_temperatures = get_background_temperatures(list_of_temperatures)
303
343
 
304
344
  assert experiment.sample
305
- return [
306
- AuxiliaryScan(
307
- instrument_session=experiment.instrument_session,
308
- pin=None,
309
- time_per_pdf=time_per_pdf,
310
- ),
311
- AuxiliaryScan(
312
- instrument_session=experiment.instrument_session,
313
- pin=StandardsPin(
314
- capillary=experiment.sample.data["capillary"], contents=None
315
- ),
316
- time_per_pdf=time_per_pdf,
317
- list_of_temperatures=list_of_temperatures,
345
+
346
+ air = AuxiliaryScan(
347
+ instrument_session=experiment.instrument_session,
348
+ pin=None,
349
+ time_per_pdf=time_per_pdf,
350
+ )
351
+ empty_capillary = AuxiliaryScan(
352
+ instrument_session=experiment.instrument_session,
353
+ pin=StandardsPin(
354
+ capillary=experiment.sample.data["capillary"], contents=None
318
355
  ),
319
- AuxiliaryScan(
320
- instrument_session=experiment.instrument_session,
321
- pin=StandardsPin(
322
- capillary=experiment.sample.data["capillary"], contents="Silicon"
323
- ),
324
- time_per_pdf=time_per_pdf,
356
+ time_per_pdf=time_per_pdf,
357
+ list_of_temperatures=list_of_temperatures,
358
+ requires=[air],
359
+ )
360
+ standard_sample = AuxiliaryScan(
361
+ instrument_session=experiment.instrument_session,
362
+ pin=StandardsPin(
363
+ capillary=experiment.sample.data["capillary"], contents="Silicon"
325
364
  ),
326
- ]
365
+ time_per_pdf=time_per_pdf,
366
+ requires=[air, empty_capillary],
367
+ )
368
+
369
+ return [standard_sample, empty_capillary, air]
327
370
 
328
371
  def _construct_auxiliary_experiment(
329
372
  self, auxiliary_scan: AuxiliaryScan, instrument_session: str
330
373
  ) -> Experiment:
331
374
  LOGGER.debug(f"Constructing experiment for auxiliary scan: {auxiliary_scan}")
332
- data: dict[str, Any] = {"time_per_pdf": auxiliary_scan.time_per_pdf}
375
+ data: dict[str, Any] = {
376
+ "time_per_pdf": auxiliary_scan.time_per_pdf,
377
+ "required_auxiliary_scans": auxiliary_scan.requires,
378
+ }
333
379
  if auxiliary_scan.list_of_temperatures:
334
380
  settle_time = (
335
381
  self._queue_params.blower_auxiliary_collection_params.settle_time_s
@@ -31,8 +31,9 @@ def get_suitable_tiled_scan(
31
31
 
32
32
  oldest_valid_time = time.time() - stale_time_s
33
33
  result: Container = (
34
- tiled_client.search(Eq("start.instrument", "i15-1"))
35
- .search(Eq("start.instrument_session", instrument_session))
34
+ tiled_client[
35
+ f"i15-1/{instrument_session.split('-')[0]}/{instrument_session}"
36
+ ]
36
37
  .search(Eq("stop.exit_status", "success"))
37
38
  .search(Comparison("ge", "stop.time", oldest_valid_time))
38
39
  .search(In("start.scan_type", list(AuxiliaryScanType)))
@@ -74,6 +75,11 @@ def get_suitable_tiled_scan(
74
75
  "list_of_temperatures"
75
76
  )
76
77
 
78
+ requires = [
79
+ TiledAuxiliary.model_validate(auxiliary_scan)
80
+ for auxiliary_scan in start_doc.get("auxiliary_scans", {}).values()
81
+ ]
82
+
77
83
  auxiliary_scan = TiledAuxiliary(
78
84
  tiled_id=tiled_id,
79
85
  instrument_session=instrument_session,
@@ -83,6 +89,7 @@ def get_suitable_tiled_scan(
83
89
  pin=pin,
84
90
  time_per_pdf=time_per_pdf,
85
91
  list_of_temperatures=list_of_temperatures,
92
+ requires=requires,
86
93
  )
87
94
  if auxiliary_scan.kind != start_doc["scan_type"]:
88
95
  LOGGER.warning(
@@ -293,6 +293,7 @@ class TaskQueue:
293
293
  self._broadcaster.broadcast(
294
294
  Event(type="call_history_update", data=self._get_call_history())
295
295
  )
296
+ self._broadcaster.broadcast(Event(type="state_update", data=self._state))
296
297
 
297
298
  async def get_next_call_once_available(self) -> BlueapiCall:
298
299
  """Waits until a call is available before returning the call. A call is
@@ -353,7 +354,11 @@ class TaskQueue:
353
354
  result (TaskResult): The result of the task from blueapi
354
355
  """
355
356
  with add_session_to_logger(call.task_request.instrument_session):
356
- tiled_ids, scan_ids = get_tiled_and_scan_ids(self._tiled_client, call)
357
+ tiled_ids, scan_ids = (
358
+ get_tiled_and_scan_ids(self._tiled_client, self.instrument, call)
359
+ if self.instrument
360
+ else ([], [])
361
+ )
357
362
  should_pause = self._converter.pause_on_complete_blueapi_call(
358
363
  call.model_copy(), result
359
364
  )
@@ -382,7 +387,12 @@ class TaskQueue:
382
387
  should_pause = self._converter.pause_on_fail_blueapi_call(
383
388
  call.model_copy(), errors
384
389
  )
385
- tiled_ids, scan_ids = get_tiled_and_scan_ids(self._tiled_client, call)
390
+
391
+ tiled_ids, scan_ids = (
392
+ get_tiled_and_scan_ids(self._tiled_client, self.instrument, call)
393
+ if self.instrument
394
+ else ([], [])
395
+ )
386
396
  LOGGER.error(f"Plan {call} has failed with the following errors: {errors}")
387
397
 
388
398
  async with self._modifying:
@@ -555,7 +565,6 @@ class TaskQueue:
555
565
  )
556
566
  self._state.paused = True
557
567
  self._state.last_pause_reason = reason
558
- self._broadcaster.broadcast(Event(type="state_update", data=self._state))
559
568
  notify(f"Queue paused: {reason}", "INFO")
560
569
 
561
570
  async def pause_queue(self, reason: PauseReason) -> QueueState:
@@ -581,7 +590,6 @@ class TaskQueue:
581
590
  LOGGER.info("Resuming queue")
582
591
  async with self._modifying:
583
592
  self._state.paused = False
584
- self._broadcaster.broadcast(Event(type="state_update", data=self._state))
585
593
  return self._state
586
594
 
587
595
  @property
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: daq-queuing-service
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: A service to queue tasks and chain BlueAPI calls
5
5
  Author-email: Jacob Williamson <jacob.williamson@diamond.ac.uk>
6
6
  License: Apache License
@@ -39,11 +39,14 @@ docs/index.md
39
39
  docs/reference.md
40
40
  docs/tutorials.md
41
41
  docs/_templates/custom-module-template.rst
42
+ docs/explanations/beamlines.md
42
43
  docs/explanations/converters.md
43
44
  docs/explanations/decisions.md
44
45
  docs/explanations/queue.md
45
46
  docs/explanations/worker.md
46
- docs/explanations/beamlines/i15-1/backgrounds_logic.drawio.png
47
+ docs/explanations/beamlines/i15-1/auxiliary_scans.md
48
+ docs/explanations/beamlines/i15-1/i15-1.md
49
+ docs/explanations/beamlines/i15-1/i15-1_aux_scans.drawio.png
47
50
  docs/explanations/decisions/0001-record-architecture-decisions.md
48
51
  docs/explanations/decisions/0002-switched-to-python-copier-template.md
49
52
  docs/explanations/decisions/COPYME
@@ -33,7 +33,10 @@
33
33
  "docs/_templates/custom-module-template.rst",
34
34
  "docs/conf.py",
35
35
  "docs/explanations.md",
36
- "docs/explanations/beamlines/i15-1/backgrounds_logic.drawio.png",
36
+ "docs/explanations/beamlines.md",
37
+ "docs/explanations/beamlines/i15-1/auxiliary_scans.md",
38
+ "docs/explanations/beamlines/i15-1/i15-1.md",
39
+ "docs/explanations/beamlines/i15-1/i15-1_aux_scans.drawio.png",
37
40
  "docs/explanations/converters.md",
38
41
  "docs/explanations/decisions.md",
39
42
  "docs/explanations/decisions/0001-record-architecture-decisions.md",
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "0.2.2",
3
+ "distance": 0,
4
+ "node": "gfddbbda69525a09291d16d6e97f3e3e28642a2b1",
5
+ "dirty": false,
6
+ "branch": "HEAD",
7
+ "node_date": "2026-11-10"
8
+ }
@@ -39,14 +39,13 @@ def mock_tiled_search(
39
39
  }
40
40
  }
41
41
 
42
- search_result = MagicMock()
43
- search_result.search = MagicMock(
42
+ search_result = MagicMock(
44
43
  return_value={"tiled_id_1": result_1, "tiled_id_2": result_2}
45
44
  )
46
45
 
47
- tiled_client.search = MagicMock(return_value=search_result)
46
+ tiled_client["ixx/cm12345/cm12345-1"].search = search_result
48
47
 
49
- return (tiled_client, search_result)
48
+ return tiled_client
50
49
 
51
50
 
52
51
  def test_get_tiled_client_instantiates_client_from_uri():
@@ -104,22 +103,21 @@ def test_get_tiled_client_adds_tiled_auth_with_client_id_and_secret_if_found(
104
103
  )
105
104
 
106
105
 
107
- def test_get_metadata_from_tiled_makes_expected_searches(
108
- mock_tiled_search: tuple[MagicMock, MagicMock],
106
+ def test_get_metadata_from_tiled_makes_expected_search(
107
+ mock_tiled_search: MagicMock,
109
108
  ):
110
- client, result = mock_tiled_search
111
- get_metadata_from_tiled(client, "cm12345-1", "bapi_task_id")
112
- client.search.assert_called_once_with(
113
- Eq(key="start.instrument_session", value="cm12345-1")
109
+ client = mock_tiled_search
110
+ get_metadata_from_tiled(client, "ixx", "cm12345-1", "bapi_task_id")
111
+ client["ixx/cm12345/cm12345-1"].search.assert_called_once_with( # type:ignore
112
+ Eq("start.blueapi_task_id", "bapi_task_id")
114
113
  )
115
- result.search.assert_called_once_with(Eq("start.blueapi_task_id", "bapi_task_id"))
116
114
 
117
115
 
118
116
  def test_get_metadata_from_tiled_returns_expected_result(
119
- mock_tiled_search: tuple[MagicMock, MagicMock],
117
+ mock_tiled_search: MagicMock,
120
118
  ):
121
- client, _ = mock_tiled_search
122
- result = get_metadata_from_tiled(client, "cm12345-1", "bapi_task_id")
119
+ client = mock_tiled_search
120
+ result = get_metadata_from_tiled(client, "ixx", "cm12345-1", "bapi_task_id")
123
121
  assert result == [ # Should be in chronological order
124
122
  (
125
123
  "tiled_id_2",
@@ -149,9 +147,9 @@ def test_get_metadata_from_tiled_returns_expected_result(
149
147
 
150
148
 
151
149
  def test_get_metadata_from_tiled_returns_empty_list_if_no_result_found(
152
- mock_tiled_search: tuple[MagicMock, MagicMock],
150
+ mock_tiled_search: MagicMock,
153
151
  ):
154
- client, search = mock_tiled_search
155
- search.search = MagicMock(return_value={})
156
- result = get_metadata_from_tiled(client, "cm12345-1", "bapi_task_id")
152
+ client = mock_tiled_search
153
+ client["ixx/cm12345/cm12345-1"].search = MagicMock(return_value={})
154
+ result = get_metadata_from_tiled(client, "ixx", "cm12345-1", "bapi_task_id")
157
155
  assert result == []