bec-server 4.3.0__tar.gz → 4.3.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.
- {bec_server-4.3.0 → bec_server-4.3.2}/PKG-INFO +1 -1
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/actors/worker.py +5 -15
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/procedures/constants.py +21 -2
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/procedures/container_utils.py +74 -5
- bec_server-4.3.2/bec_server/procedures/container_worker.py +152 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/procedures/manager.py +82 -117
- bec_server-4.3.2/bec_server/procedures/oop_worker_base.py +603 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/procedures/protocol.py +11 -0
- bec_server-4.3.2/bec_server/procedures/queue_manager.py +598 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/procedures/subprocess_worker.py +38 -18
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/procedures/worker_base.py +44 -10
- {bec_server-4.3.0 → bec_server-4.3.2}/pyproject.toml +1 -1
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_actors/test_actors.py +27 -2
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_container_utils.py +93 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_procedure_container_worker.py +143 -2
- bec_server-4.3.2/tests/tests_scan_server/test_procedure_queue_pool.py +608 -0
- bec_server-4.3.2/tests/tests_scan_server/test_procedure_submission.py +137 -0
- bec_server-4.3.2/tests/tests_scan_server/test_procedure_subprocess_worker.py +490 -0
- bec_server-4.3.2/tests/tests_scan_server/test_procedures.py +313 -0
- bec_server-4.3.0/bec_server/procedures/container_worker.py +0 -78
- bec_server-4.3.0/bec_server/procedures/oop_worker_base.py +0 -248
- bec_server-4.3.0/tests/tests_scan_server/test_procedures.py +0 -678
- {bec_server-4.3.0 → bec_server-4.3.2}/.gitignore +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/.zed/debug.json +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/README.md +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/__init__.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/actors/__init__.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/actors/actor.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/actors/builtin_actor_manager.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/actors/manager.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/actors/scan_interlock.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/bec_server_utils/__init__.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/bec_server_utils/launch.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/bec_server_utils/service_handler.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/bec_server_utils/subprocess_launch.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/bec_server_utils/tmux_launch.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/data_processing/__init__.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/data_processing/cli/__init__.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/data_processing/cli/launch.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/data_processing/dap_server.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/data_processing/dap_service.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/data_processing/dap_service_manager.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/data_processing/lmfit1d_service.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/device_server/__init__.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/device_server/bec_message_handler.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/device_server/cli/__init__.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/device_server/cli/launch.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/device_server/device_server.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/device_server/devices/__init__.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/device_server/devices/config_update_handler.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/device_server/devices/device_serializer.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/device_server/devices/devicemanager.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/device_server/friendly_device_exceptions.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/device_server/ophyd_callback_monitor.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/device_server/rpc_handler.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/device_server/tests/__init__.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/device_server/tests/utils.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/file_writer/__init__.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/file_writer/async_writer.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/file_writer/cli/__init__.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/file_writer/cli/launch.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/file_writer/default_writer.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/file_writer/file_writer.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/file_writer/file_writer_manager.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/file_writer/merged_dicts.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/procedures/Containerfile.bec_linux_base +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/procedures/Containerfile.requirements +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/procedures/Containerfile.worker +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/procedures/__init__.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/procedures/_dev_runner.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/procedures/builtin_procedures.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/procedures/procedure_registry.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_bundler/__init__.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_bundler/bec_emitter.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_bundler/cli/__init__.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_bundler/cli/launch.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_bundler/emitter.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_bundler/scan_bundler.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/__init__.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/beamline_state_manager.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/cli/__init__.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/cli/launch.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/device_lock_registry.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/direct_scan_worker.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/errors.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/instruction_handler.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scan_assembler.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scan_guard.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scan_manager.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scan_queue.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scan_server.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scan_worker.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/__init__.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/acquire.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/cont_line_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/device_rpc.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/fermat_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/grid_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/hexagonal_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/line_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/line_sweep_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/list_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/log_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/move.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/multi_region_grid_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/multi_region_line_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/path_optimization.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/position_generators.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/round_roi_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/round_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/scan_actions.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/scan_argument_modifier.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/scan_base.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/scan_components.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/scan_modifier.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/scan_status.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/time_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/scans/updated_move.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/tests/__init__.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/tests/fixtures.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/tests/scan_fixtures.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/tests/scan_hook_tests.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scan_server/tests/utils.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scihub/__init__.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scihub/atlas/__init__.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scihub/atlas/atlas_active_client_emitter.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scihub/atlas/atlas_connector.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scihub/atlas/atlas_forwarder.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scihub/atlas/atlas_metadata_handler.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scihub/atlas/atlas_plugin_repo_emitter.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scihub/atlas/config_handler.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scihub/cli/__init__.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scihub/cli/launch.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scihub/scihub.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scihub/service_handler/__init__.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/scihub/service_handler/service_handler.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/test/__init__.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/test/actor_test_utils.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/bec_server/test/helpers.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_bec_server_utils/test_main.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_bec_server_utils/test_service_handler.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_bec_server_utils/test_subprocess_launch.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_bec_server_utils/test_tmux_launch.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_data_processing/conftest.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_data_processing/test_dap_cli_launch.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_data_processing/test_dap_server.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_data_processing/test_dap_service_manager.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_data_processing/test_lmfit1d_service.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_device_server/conftest.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_device_server/test_config_handler.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_device_server/test_device_instructions.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_device_server/test_device_manager_ds.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_device_server/test_device_serializer.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_device_server/test_device_server.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_device_server/test_device_server_cli_launch.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_device_server/test_ophyd_callback_monitor.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_device_server/test_rpc_handler.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_file_writer/conftest.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_file_writer/test_async_file_writer.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_file_writer/test_file_writer.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_file_writer/test_file_writer_cli_launch.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_file_writer/test_file_writer_manager.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_bundler/conftest.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_bundler/test_bec_emitter.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_bundler/test_scan_bundler.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_bundler/test_scan_bundler_cli_launch.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/conftest.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/__init__.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_acquire.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_cont_line_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_device_rpc_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_fermat_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_grid_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_hexagonal_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_line_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_line_sweep_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_list_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_log_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_move_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_multi_region_grid_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_multi_region_line_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_position_preview.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_relative_scan_return_to_start.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_round_roi_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_round_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_scan_actions.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_scan_components.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_scan_status.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_time_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/scans/test_updated_move_scan.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_beamline_state_manager.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_builtin_actor_manager.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_device_lock_registry.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_direct_scan_worker.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_instruction_handler.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_path_optimization.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_scan_argument_modifier.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_scan_assembler.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_scan_fixture_imports.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_scan_guard.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_scan_interlock.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_scan_modifier.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_scan_server_cli_launch.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_scan_server_queue.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_scan_server_scan_manager.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scan_server/test_scan_worker.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scihub/conftest.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scihub/test_atlas_active_client_emitter.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scihub/test_atlas_config_handler.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scihub/test_atlas_connector.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scihub/test_atlas_forwarder.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scihub/test_atlas_metadata_handler.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scihub/test_atlas_plugin_repo_emitter.py +0 -0
- {bec_server-4.3.0 → bec_server-4.3.2}/tests/tests_scihub/test_scihub_cli_launch.py +0 -0
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import importlib
|
|
2
2
|
import os
|
|
3
|
-
from contextlib import redirect_stdout
|
|
4
3
|
from inspect import isclass
|
|
5
4
|
|
|
6
5
|
from bec_lib.client import BECClient
|
|
7
|
-
from bec_lib.logger import
|
|
6
|
+
from bec_lib.logger import bec_logger
|
|
8
7
|
from bec_lib.messages import ProcedureWorkerStatus
|
|
9
|
-
from bec_lib.redis_connector import RedisConnector
|
|
10
8
|
from bec_server.actors.actor import ActorBase
|
|
11
|
-
from bec_server.procedures.oop_worker_base import
|
|
9
|
+
from bec_server.procedures.oop_worker_base import get_env, push_status, setup
|
|
12
10
|
from bec_server.procedures.subprocess_worker import SubProcessWorker
|
|
13
11
|
|
|
14
12
|
logger = bec_logger.logger
|
|
@@ -53,20 +51,12 @@ def get_actor_env():
|
|
|
53
51
|
def main():
|
|
54
52
|
env, helper, client, conn = setup(get_env())
|
|
55
53
|
actor_env = get_actor_env()
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
with redirect_stdout(output_diverter):
|
|
59
|
-
logger.add(
|
|
60
|
-
output_diverter,
|
|
61
|
-
level=LogLevel.SUCCESS,
|
|
62
|
-
format=bec_logger.formatting(is_container=True),
|
|
63
|
-
filter=bec_logger.filter(),
|
|
64
|
-
)
|
|
65
|
-
logger.success(f"Starting ActorProcedureWorker with env: {actor_env}")
|
|
54
|
+
# The parent SubProcessWorker streams stdout and stderr to Redis.
|
|
55
|
+
logger.success(f"Starting ActorProcedureWorker with env: {actor_env}")
|
|
66
56
|
push_status(conn, env["queue"], ProcedureWorkerStatus.IDLE)
|
|
67
57
|
actor_procedure(bec=client, **actor_env)
|
|
58
|
+
push_status(conn, env["queue"], ProcedureWorkerStatus.FINISHED)
|
|
68
59
|
conn.shutdown()
|
|
69
|
-
logger_connector.shutdown()
|
|
70
60
|
|
|
71
61
|
|
|
72
62
|
if __name__ == "__main__":
|
|
@@ -18,6 +18,7 @@ class OopWorkerEnv(TypedDict):
|
|
|
18
18
|
queue: str
|
|
19
19
|
timeout_s: str
|
|
20
20
|
client_class: NotRequired[BecClientType]
|
|
21
|
+
worker_id: NotRequired[str]
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
P = ParamSpec("P")
|
|
@@ -33,7 +34,25 @@ class BecProcedure(Protocol[P]):
|
|
|
33
34
|
def __call__(self, *args: P.args, **kwargs: P.kwargs) -> None: ...
|
|
34
35
|
|
|
35
36
|
|
|
36
|
-
class
|
|
37
|
+
class ProcedureWorkerFailure(str, Enum):
|
|
38
|
+
"""Fixed, credential-free descriptions suitable for public execution status."""
|
|
39
|
+
|
|
40
|
+
STARTUP = "Procedure worker startup failed"
|
|
41
|
+
AUTHENTICATION = "Procedure worker authentication failed"
|
|
42
|
+
EXITED = "Procedure worker exited unexpectedly"
|
|
43
|
+
INPUT_CLOSED = "Procedure worker input closed unexpectedly"
|
|
44
|
+
ABORTED = "Procedure worker was aborted"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class ProcedureWorkerError(RuntimeError):
|
|
48
|
+
"""Worker failure with an optional safe category for public status."""
|
|
49
|
+
|
|
50
|
+
def __init__(self, *args: object, failure: ProcedureWorkerFailure | None = None) -> None:
|
|
51
|
+
"""Default to the public failure description unless internal details are supplied."""
|
|
52
|
+
if not args and failure is not None:
|
|
53
|
+
args = (failure.value,)
|
|
54
|
+
super().__init__(*args)
|
|
55
|
+
self.failure = failure
|
|
37
56
|
|
|
38
57
|
|
|
39
58
|
class WorkerAlreadyExists(ProcedureWorkerError): ...
|
|
@@ -48,7 +67,7 @@ class NoImage(ProcedureWorkerError): ...
|
|
|
48
67
|
@dataclass(frozen=True)
|
|
49
68
|
class _WORKER:
|
|
50
69
|
MAX_WORKERS = 10
|
|
51
|
-
QUEUE_TIMEOUT_S =
|
|
70
|
+
QUEUE_TIMEOUT_S = 60
|
|
52
71
|
DEFAULT_QUEUE = "primary"
|
|
53
72
|
|
|
54
73
|
|
|
@@ -10,7 +10,7 @@ from typing import Iterator, Literal, cast
|
|
|
10
10
|
|
|
11
11
|
from podman import PodmanClient
|
|
12
12
|
from podman.domain.containers import Container
|
|
13
|
-
from podman.errors import APIError
|
|
13
|
+
from podman.errors import APIError, NotFound
|
|
14
14
|
|
|
15
15
|
from bec_lib.logger import bec_logger
|
|
16
16
|
from bec_server.procedures.constants import (
|
|
@@ -81,6 +81,67 @@ class _PodmanUtilsBase(ContainerCommandBackend):
|
|
|
81
81
|
tag=f"{PROCEDURE.CONTAINER.IMAGE_NAME}:v{PROCEDURE.BEC_VERSION}",
|
|
82
82
|
)
|
|
83
83
|
|
|
84
|
+
def run_interactive(
|
|
85
|
+
self,
|
|
86
|
+
image_tag: str,
|
|
87
|
+
environment: OopWorkerEnv,
|
|
88
|
+
volumes: list[VolumeSpec],
|
|
89
|
+
command: str,
|
|
90
|
+
pod_name: str | None = None,
|
|
91
|
+
container_name: str | None = None,
|
|
92
|
+
) -> subprocess.Popen:
|
|
93
|
+
"""Attach process pipes so private worker bootstrap never enters Podman metadata.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
image_tag (str): Worker image.
|
|
97
|
+
environment (OopWorkerEnv): Non-secret worker settings.
|
|
98
|
+
volumes (list[VolumeSpec]): Code mounts.
|
|
99
|
+
command (str): Worker entry point.
|
|
100
|
+
pod_name (str | None): Existing Podman pod.
|
|
101
|
+
container_name (str | None): Unique worker container name.
|
|
102
|
+
Returns:
|
|
103
|
+
subprocess.Popen: Attached process with stdin and separate output pipes.
|
|
104
|
+
"""
|
|
105
|
+
prefix = self._cli_prefix()
|
|
106
|
+
args = [*prefix, "create", "-i"]
|
|
107
|
+
args.extend(_multi_args_from_dict("-e", environment))
|
|
108
|
+
for volume in volumes:
|
|
109
|
+
args.extend(
|
|
110
|
+
[
|
|
111
|
+
"-v",
|
|
112
|
+
f"{volume['source']}:{volume['target']}{':ro' if volume['read_only'] else ''}",
|
|
113
|
+
]
|
|
114
|
+
)
|
|
115
|
+
if pod_name:
|
|
116
|
+
args.extend(["--pod", pod_name])
|
|
117
|
+
if container_name:
|
|
118
|
+
args.extend(["--name", container_name])
|
|
119
|
+
# Create synchronously: cancelling the attached start cannot leave a later
|
|
120
|
+
# `podman run` creating an orphan container after cleanup has returned.
|
|
121
|
+
container_id = _run_and_capture_error(*args, image_tag, command).stdout.decode().strip()
|
|
122
|
+
try:
|
|
123
|
+
return subprocess.Popen(
|
|
124
|
+
[*prefix, "start", "--attach", "--interactive", container_id],
|
|
125
|
+
stdin=subprocess.PIPE,
|
|
126
|
+
stdout=subprocess.PIPE,
|
|
127
|
+
stderr=subprocess.PIPE,
|
|
128
|
+
bufsize=0,
|
|
129
|
+
)
|
|
130
|
+
except BaseException:
|
|
131
|
+
self.remove(container_id)
|
|
132
|
+
raise
|
|
133
|
+
|
|
134
|
+
def _cli_prefix(self) -> list[str]:
|
|
135
|
+
return ["podman", "--url", self.uri] if isinstance(self, PodmanApiUtils) else ["podman"]
|
|
136
|
+
|
|
137
|
+
def remove(self, id: str) -> None:
|
|
138
|
+
"""Remove a stopped or starting worker container, preventing a later start.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
id (str): Container name or ID.
|
|
142
|
+
"""
|
|
143
|
+
_run_and_capture_error(*self._cli_prefix(), "rm", "--force", "--ignore", id)
|
|
144
|
+
|
|
84
145
|
|
|
85
146
|
class PodmanApiOutput(ContainerCommandOutput):
|
|
86
147
|
def __init__(self, command_output: Iterator[bytes]):
|
|
@@ -157,7 +218,10 @@ class PodmanApiUtils(_PodmanUtilsBase):
|
|
|
157
218
|
|
|
158
219
|
def state(self, id: str) -> PodmanContainerStates | None:
|
|
159
220
|
with PodmanClient(base_url=self.uri) as client:
|
|
160
|
-
|
|
221
|
+
try:
|
|
222
|
+
status = client.containers.get(id).status
|
|
223
|
+
except NotFound:
|
|
224
|
+
return None
|
|
161
225
|
if status == "unknown":
|
|
162
226
|
return None
|
|
163
227
|
return PodmanContainerStates(status)
|
|
@@ -220,7 +284,7 @@ class PodmanCliUtils(_PodmanUtilsBase):
|
|
|
220
284
|
_name_arg = ["--replace", "--name", container_name] if container_name else []
|
|
221
285
|
if container_name:
|
|
222
286
|
# in case of incomplete cleanup previously, even with --replace it is possible to get an error
|
|
223
|
-
_run_and_capture_error("podman", "rm", "-f", container_name)
|
|
287
|
+
_run_and_capture_error("podman", "rm", "-f", "--ignore", container_name)
|
|
224
288
|
return (
|
|
225
289
|
_run_and_capture_error(
|
|
226
290
|
"podman",
|
|
@@ -251,14 +315,19 @@ class PodmanCliUtils(_PodmanUtilsBase):
|
|
|
251
315
|
|
|
252
316
|
def logs(self, id: str) -> list[str]:
|
|
253
317
|
try:
|
|
254
|
-
|
|
318
|
+
output = _run_and_capture_error("podman", "logs", id)
|
|
319
|
+
return (output.stdout + output.stderr).decode(errors="replace").splitlines()
|
|
255
320
|
except ProcedureWorkerError as e:
|
|
256
321
|
logger.error(e)
|
|
257
322
|
return [f"No logs found for container {id}\n"]
|
|
258
323
|
|
|
259
324
|
def state(self, id: str) -> PodmanContainerStates | None:
|
|
260
325
|
for container in self._podman_ls_json():
|
|
261
|
-
if
|
|
326
|
+
if (
|
|
327
|
+
container["Id"] == id
|
|
328
|
+
or container["Id"].startswith(id)
|
|
329
|
+
or id in container.get("Names", [])
|
|
330
|
+
):
|
|
262
331
|
if names := container.get("Names"):
|
|
263
332
|
logger.debug(f"Container {names[0]} status: {container['State']}")
|
|
264
333
|
return PodmanContainerStates(container["State"])
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import time
|
|
2
|
+
|
|
3
|
+
from bec_lib.logger import bec_logger
|
|
4
|
+
from bec_lib.redis_connector import RedisConnector
|
|
5
|
+
from bec_server.procedures.constants import PROCEDURE, PodmanContainerStates
|
|
6
|
+
from bec_server.procedures.container_utils import get_backend
|
|
7
|
+
from bec_server.procedures.oop_worker_base import (
|
|
8
|
+
main, # temporarily needed before update of base image on release
|
|
9
|
+
)
|
|
10
|
+
from bec_server.procedures.oop_worker_base import PROCESS_TIMEOUT, OutOfProcessWorkerBase
|
|
11
|
+
from bec_server.procedures.protocol import ContainerCommandBackend
|
|
12
|
+
|
|
13
|
+
logger = bec_logger.logger
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ContainerProcedureWorker(OutOfProcessWorkerBase):
|
|
17
|
+
"""A worker which runs scripts in a container with a full BEC environment,
|
|
18
|
+
mounted from the filesystem, and only access to Redis"""
|
|
19
|
+
|
|
20
|
+
# The Podman client is a thin wrapper around the libpod API
|
|
21
|
+
# documented at https://docs.podman.io/en/latest/_static/api.html
|
|
22
|
+
# which is more detailed than the podman-py documentation
|
|
23
|
+
|
|
24
|
+
def _setup_execution_environment(self):
|
|
25
|
+
self._backend: ContainerCommandBackend = get_backend()
|
|
26
|
+
image_tag = f"{PROCEDURE.CONTAINER.IMAGE_NAME}:v{PROCEDURE.BEC_VERSION}"
|
|
27
|
+
self.container_name = (
|
|
28
|
+
f"bec_procedure_{PROCEDURE.BEC_VERSION}_{self._worker_id or self._queue}"
|
|
29
|
+
)
|
|
30
|
+
if not self._backend.image_exists(image_tag):
|
|
31
|
+
self._backend.build_worker_image()
|
|
32
|
+
environment = self._worker_environment() | self._additional_env
|
|
33
|
+
if self._worker_id is not None:
|
|
34
|
+
self._container_id = self.container_name
|
|
35
|
+
self._process = self._backend.run_interactive(
|
|
36
|
+
image_tag,
|
|
37
|
+
environment,
|
|
38
|
+
[
|
|
39
|
+
{
|
|
40
|
+
"source": str(PROCEDURE.CONTAINER.DEPLOYMENT_PATH),
|
|
41
|
+
"target": "/bec",
|
|
42
|
+
"type": "bind",
|
|
43
|
+
"read_only": True,
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
PROCEDURE.CONTAINER.COMMAND,
|
|
47
|
+
pod_name=PROCEDURE.CONTAINER.POD_NAME,
|
|
48
|
+
container_name=self.container_name,
|
|
49
|
+
)
|
|
50
|
+
output_conn = RedisConnector([self._redis_server], name="Procedure container output")
|
|
51
|
+
try:
|
|
52
|
+
if self._control_credentials is not None:
|
|
53
|
+
output_conn.authenticate(
|
|
54
|
+
username=self._control_credentials["username"] or "default",
|
|
55
|
+
password=self._control_credentials["token"],
|
|
56
|
+
)
|
|
57
|
+
self._start_output_capture(output_conn)
|
|
58
|
+
except BaseException:
|
|
59
|
+
output_conn.shutdown()
|
|
60
|
+
self._kill_process()
|
|
61
|
+
raise
|
|
62
|
+
return
|
|
63
|
+
self._container_id = self._backend.run(
|
|
64
|
+
image_tag,
|
|
65
|
+
environment,
|
|
66
|
+
[
|
|
67
|
+
{
|
|
68
|
+
"source": str(PROCEDURE.CONTAINER.DEPLOYMENT_PATH),
|
|
69
|
+
"target": "/bec",
|
|
70
|
+
"type": "bind",
|
|
71
|
+
"read_only": True,
|
|
72
|
+
}
|
|
73
|
+
],
|
|
74
|
+
PROCEDURE.CONTAINER.COMMAND,
|
|
75
|
+
pod_name=PROCEDURE.CONTAINER.POD_NAME,
|
|
76
|
+
container_name=self.container_name,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
def _ending_or_ended(self):
|
|
80
|
+
if self._worker_id is not None:
|
|
81
|
+
return self._process.poll() is not None
|
|
82
|
+
return self._backend.state(self._container_id) in [
|
|
83
|
+
PodmanContainerStates.EXITED,
|
|
84
|
+
PodmanContainerStates.STOPPED,
|
|
85
|
+
PodmanContainerStates.STOPPING,
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
def _kill_process(self):
|
|
89
|
+
if self._worker_id is not None:
|
|
90
|
+
# The attached CLI can fail while the container is still running.
|
|
91
|
+
terminal = (
|
|
92
|
+
None,
|
|
93
|
+
PodmanContainerStates.CREATED,
|
|
94
|
+
PodmanContainerStates.EXITED,
|
|
95
|
+
PodmanContainerStates.STOPPED,
|
|
96
|
+
)
|
|
97
|
+
if self._backend.state(self.container_name) not in terminal:
|
|
98
|
+
self._backend.interrupt(self.container_name)
|
|
99
|
+
deadline = time.monotonic() + PROCESS_TIMEOUT
|
|
100
|
+
while time.monotonic() < deadline:
|
|
101
|
+
if self._backend.state(self.container_name) in terminal:
|
|
102
|
+
break
|
|
103
|
+
time.sleep(0.1)
|
|
104
|
+
else:
|
|
105
|
+
self._backend.kill(self.container_name)
|
|
106
|
+
deadline = time.monotonic() + PROCESS_TIMEOUT
|
|
107
|
+
while self._backend.state(self.container_name) not in terminal:
|
|
108
|
+
if time.monotonic() >= deadline:
|
|
109
|
+
raise RuntimeError("Procedure container failed to stop")
|
|
110
|
+
time.sleep(0.1)
|
|
111
|
+
# Creation completed before the launcher was started, so removal also
|
|
112
|
+
# prevents an attached start that has not reached the engine yet.
|
|
113
|
+
self._backend.remove(self.container_name)
|
|
114
|
+
if self._process.stdin is not None:
|
|
115
|
+
self._process.stdin.close()
|
|
116
|
+
try:
|
|
117
|
+
self._process.wait(PROCESS_TIMEOUT)
|
|
118
|
+
except Exception:
|
|
119
|
+
self._process.kill()
|
|
120
|
+
self._process.wait(PROCESS_TIMEOUT)
|
|
121
|
+
return
|
|
122
|
+
if not self._ending_or_ended():
|
|
123
|
+
self._backend.interrupt(self.container_name)
|
|
124
|
+
start = time.monotonic()
|
|
125
|
+
while time.monotonic() < start + PROCESS_TIMEOUT:
|
|
126
|
+
if self._ending_or_ended():
|
|
127
|
+
return
|
|
128
|
+
time.sleep(0.2)
|
|
129
|
+
logger.warning(
|
|
130
|
+
f"Procedure worker {self._container_id} for queue {self._queue} failed to shut down, killing."
|
|
131
|
+
)
|
|
132
|
+
self._backend.kill(self.container_name)
|
|
133
|
+
|
|
134
|
+
def abort_execution(self, execution_id: str):
|
|
135
|
+
"""Abort the execution with the given id. Has no effect if the given ID is not the current job"""
|
|
136
|
+
if execution_id == self._current_execution_id:
|
|
137
|
+
self._backend.kill(self._container_id)
|
|
138
|
+
self._helper.remove_from_active.by_exec_id(execution_id)
|
|
139
|
+
logger.info(
|
|
140
|
+
f"Aborting execution {execution_id}, restarting worker for queue: {self._queue}"
|
|
141
|
+
)
|
|
142
|
+
self._setup_execution_environment()
|
|
143
|
+
|
|
144
|
+
def logs(self):
|
|
145
|
+
if self._worker_id is not None:
|
|
146
|
+
if self._process.poll() is not None:
|
|
147
|
+
self._join_output()
|
|
148
|
+
with self._output_lock:
|
|
149
|
+
return "".join(self._output_logs).splitlines()
|
|
150
|
+
if self._container_id is None:
|
|
151
|
+
return [""]
|
|
152
|
+
return self._backend.logs(self._container_id)
|