From cc7600b4207cd4c7b45423c7c829889f61e70555 Mon Sep 17 00:00:00 2001 From: yxd92326 Date: Thu, 4 Sep 2025 08:42:15 +0100 Subject: [PATCH 1/5] Client should use session_control --- src/murfey/client/contexts/spa.py | 2 +- src/murfey/server/api/session_control.py | 10 ++++++++++ src/murfey/util/route_manifest.yaml | 7 +++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/murfey/client/contexts/spa.py b/src/murfey/client/contexts/spa.py index d382b1f06..476d22ca5 100644 --- a/src/murfey/client/contexts/spa.py +++ b/src/murfey/client/contexts/spa.py @@ -302,7 +302,7 @@ def _position_analysis( data_collection_group = ( capture_get( base_url=str(environment.url.geturl()), - router_name="session_info.router", + router_name="session_control.router", function_name="get_dc_groups", token=self._token, session_id=environment.murfey_session, diff --git a/src/murfey/server/api/session_control.py b/src/murfey/server/api/session_control.py index 3dc27adbb..d376abf07 100644 --- a/src/murfey/server/api/session_control.py +++ b/src/murfey/server/api/session_control.py @@ -165,6 +165,16 @@ def remove_session(session_id: MurfeySessionID, db=murfey_db): remove_session_by_id(session_id, db) +@router.get("/sessions/{session_id}/data_collection_groups") +def get_dc_groups( + session_id: MurfeySessionID, db=murfey_db +) -> Dict[str, DataCollectionGroup]: + data_collection_groups = db.exec( + select(DataCollectionGroup).where(DataCollectionGroup.session_id == session_id) + ).all() + return {dcg.tag: dcg for dcg in data_collection_groups} + + @router.post("/sessions/{session_id}/successful_processing") def register_processing_success_in_ispyb( session_id: MurfeySessionID, db=ispyb_db, murfey_db=murfey_db diff --git a/src/murfey/util/route_manifest.yaml b/src/murfey/util/route_manifest.yaml index 4a7d080f1..79de069e5 100644 --- a/src/murfey/util/route_manifest.yaml +++ b/src/murfey/util/route_manifest.yaml @@ -826,6 +826,13 @@ murfey.server.api.session_control.router: type: int methods: - DELETE + - path: /session_info/sessions/{session_id}/data_collection_groups + function: get_dc_groups + path_params: + - name: session_id + type: int + methods: + - GET - path: /session_control/sessions/{session_id}/successful_processing function: register_processing_success_in_ispyb path_params: From cd843c42a2f82192685898bae106b199c1ad317b Mon Sep 17 00:00:00 2001 From: yxd92326 Date: Thu, 4 Sep 2025 08:48:03 +0100 Subject: [PATCH 2/5] Wrong variable name --- src/murfey/util/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/murfey/util/client.py b/src/murfey/util/client.py index 21ca15536..1b1119aea 100644 --- a/src/murfey/util/client.py +++ b/src/murfey/util/client.py @@ -85,7 +85,7 @@ def capture_post( response = requests.Response() if response.status_code != 200: logger.warning( - f"Response to post to {url} with data {json} had status code " + f"Response to post to {url} with data {data} had status code " f"{response.status_code}. The reason given was {response.reason}" ) client_config = read_config() From 8669596b15150c2f9cf77a2c2a336f2845f27412 Mon Sep 17 00:00:00 2001 From: yxd92326 Date: Thu, 4 Sep 2025 09:00:13 +0100 Subject: [PATCH 3/5] Move destinations function and give it token --- src/murfey/client/destinations.py | 90 ++++++++++++++++++++++++++ src/murfey/client/multigrid_control.py | 3 +- src/murfey/client/tui/app.py | 3 +- src/murfey/client/tui/screens.py | 83 +----------------------- 4 files changed, 97 insertions(+), 82 deletions(-) create mode 100644 src/murfey/client/destinations.py diff --git a/src/murfey/client/destinations.py b/src/murfey/client/destinations.py new file mode 100644 index 000000000..bae70ce12 --- /dev/null +++ b/src/murfey/client/destinations.py @@ -0,0 +1,90 @@ +from __future__ import annotations + +import logging +from pathlib import Path +from typing import Dict + +from murfey.client.analyser import Analyser +from murfey.client.instance_environment import ( + MurfeyInstanceEnvironment, + global_env_lock, +) +from murfey.util.client import capture_get, capture_post + +logger = logging.getLogger("murfey.client.destinations") + + +def determine_default_destination( + visit: str, + source: Path, + destination: str, + environment: MurfeyInstanceEnvironment, + analysers: Dict[Path, Analyser], + token: str, + touch: bool = False, + extra_directory: str = "", + include_mid_path: bool = True, + use_suggested_path: bool = True, +) -> str: + machine_data = capture_get( + base_url=str(environment.url.geturl()), + router_name="session_control.router", + function_name="machine_info_by_instrument", + token=token, + instrument_name=environment.instrument_name, + ).json() + _default = "" + if environment.processing_only_mode and environment.sources: + logger.info(f"Processing only mode with sources {environment.sources}") + _default = str(environment.sources[0].absolute()) or str(Path.cwd()) + elif machine_data.get("data_directories"): + for data_dir in machine_data["data_directories"]: + if source.absolute() == Path(data_dir).absolute(): + _default = f"{destination}/{visit}" + break + else: + try: + mid_path = source.absolute().relative_to(Path(data_dir).absolute()) + if use_suggested_path: + with global_env_lock: + source_name = ( + source.name + if source.name != "Images-Disc1" + else source.parent.name + ) + if environment.destination_registry.get(source_name): + _default = environment.destination_registry[source_name] + else: + suggested_path_response = capture_post( + base_url=str(environment.url.geturl()), + router_name="file_io_instrument.router", + function_name="suggest_path", + token=token, + visit_name=visit, + session_id=environment.murfey_session, + data={ + "base_path": f"{destination}/{visit}/{mid_path.parent if include_mid_path else ''}/raw", + "touch": touch, + "extra_directory": extra_directory, + }, + ) + if suggested_path_response is None: + raise RuntimeError("Murfey server is unreachable") + _default = suggested_path_response.json().get( + "suggested_path" + ) + environment.destination_registry[source_name] = _default + else: + _default = f"{destination}/{visit}/{mid_path if include_mid_path else source.name}" + break + except (ValueError, KeyError): + _default = "" + else: + _default = "" + else: + _default = f"{destination}/{visit}" + return ( + _default + f"/{extra_directory}" + if not _default.endswith("/") + else _default + f"{extra_directory}" + ) diff --git a/src/murfey/client/multigrid_control.py b/src/murfey/client/multigrid_control.py index 65af22485..23178b770 100644 --- a/src/murfey/client/multigrid_control.py +++ b/src/murfey/client/multigrid_control.py @@ -14,9 +14,9 @@ from murfey.client.analyser import Analyser from murfey.client.contexts.spa import SPAModularContext from murfey.client.contexts.tomo import TomographyContext +from murfey.client.destinations import determine_default_destination from murfey.client.instance_environment import MurfeyInstanceEnvironment from murfey.client.rsync import RSyncer, RSyncerUpdate, TransferResult -from murfey.client.tui.screens import determine_default_destination from murfey.client.watchdir import DirWatcher from murfey.util import posix_path from murfey.util.client import ( @@ -267,6 +267,7 @@ def _start_rsyncer_multigrid( self._environment.default_destinations[source], self._environment, self.analysers or {}, + self.token, touch=True, extra_directory=extra_directory, include_mid_path=include_mid_path, diff --git a/src/murfey/client/tui/app.py b/src/murfey/client/tui/app.py index bdf20469c..2c1bda452 100644 --- a/src/murfey/client/tui/app.py +++ b/src/murfey/client/tui/app.py @@ -16,6 +16,7 @@ from murfey.client.analyser import Analyser from murfey.client.contexts.spa import SPAModularContext from murfey.client.contexts.tomo import TomographyContext +from murfey.client.destinations import determine_default_destination from murfey.client.instance_environment import MurfeyInstanceEnvironment from murfey.client.rsync import RSyncer, RSyncerUpdate, TransferResult from murfey.client.tui.screens import ( @@ -27,7 +28,6 @@ VisitCreation, VisitSelection, WaitingScreen, - determine_default_destination, ) from murfey.client.tui.status_bar import StatusBar from murfey.client.watchdir import DirWatcher @@ -177,6 +177,7 @@ def _start_rsyncer_multigrid( self._default_destinations[source], self._environment, self.analysers, + token, touch=True, extra_directory=extra_directory, include_mid_path=include_mid_path, diff --git a/src/murfey/client/tui/screens.py b/src/murfey/client/tui/screens.py index fc356b0b7..780eadf9d 100644 --- a/src/murfey/client/tui/screens.py +++ b/src/murfey/client/tui/screens.py @@ -45,14 +45,10 @@ ) from werkzeug.utils import secure_filename -from murfey.client.analyser import Analyser from murfey.client.contexts.spa import SPAModularContext from murfey.client.contexts.tomo import TomographyContext +from murfey.client.destinations import determine_default_destination from murfey.client.gain_ref import determine_gain_ref -from murfey.client.instance_environment import ( - MurfeyInstanceEnvironment, - global_env_lock, -) from murfey.client.rsync import RSyncer from murfey.util import posix_path from murfey.util.client import ( @@ -72,81 +68,6 @@ instrument_name = read_config()["Murfey"].get("instrument_name", "") -def determine_default_destination( - visit: str, - source: Path, - destination: str, - environment: MurfeyInstanceEnvironment, - analysers: Dict[Path, Analyser], - touch: bool = False, - extra_directory: str = "", - include_mid_path: bool = True, - use_suggested_path: bool = True, -) -> str: - machine_data = capture_get( - base_url=str(environment.url.geturl()), - router_name="session_control.router", - function_name="machine_info_by_instrument", - token=token, - instrument_name=environment.instrument_name, - ).json() - _default = "" - if environment.processing_only_mode and environment.sources: - log.info(f"Processing only mode with sources {environment.sources}") - _default = str(environment.sources[0].absolute()) or str(Path.cwd()) - elif machine_data.get("data_directories"): - for data_dir in machine_data["data_directories"]: - if source.absolute() == Path(data_dir).absolute(): - _default = f"{destination}/{visit}" - break - else: - try: - mid_path = source.absolute().relative_to(Path(data_dir).absolute()) - if use_suggested_path: - with global_env_lock: - source_name = ( - source.name - if source.name != "Images-Disc1" - else source.parent.name - ) - if environment.destination_registry.get(source_name): - _default = environment.destination_registry[source_name] - else: - suggested_path_response = capture_post( - base_url=str(environment.url.geturl()), - router_name="file_io_instrument.router", - function_name="suggest_path", - token=token, - visit_name=visit, - session_id=environment.murfey_session, - data={ - "base_path": f"{destination}/{visit}/{mid_path.parent if include_mid_path else ''}/raw", - "touch": touch, - "extra_directory": extra_directory, - }, - ) - if suggested_path_response is None: - raise RuntimeError("Murfey server is unreachable") - _default = suggested_path_response.json().get( - "suggested_path" - ) - environment.destination_registry[source_name] = _default - else: - _default = f"{destination}/{visit}/{mid_path if include_mid_path else source.name}" - break - except (ValueError, KeyError): - _default = "" - else: - _default = "" - else: - _default = f"{destination}/{visit}" - return ( - _default + f"/{extra_directory}" - if not _default.endswith("/") - else _default + f"{extra_directory}" - ) - - class InputResponse(NamedTuple): question: str allowed_responses: List[str] | None = None @@ -349,6 +270,7 @@ def on_button_pressed(self, event: Button.Pressed) -> None: defd, self.app._environment, self.app.analysers, + token, touch=True, ) visit_path = defd + f"/{text}" @@ -1077,6 +999,7 @@ def compose(self): f"{datetime.now().year}", self.app._environment, self.app.analysers, + token, touch=True, ) if dest and dest in destinations: From 4f7daebb14fe7aff46a759616003d052894ee1b9 Mon Sep 17 00:00:00 2001 From: yxd92326 Date: Thu, 4 Sep 2025 09:04:35 +0100 Subject: [PATCH 4/5] Change the model for failed posts --- src/murfey/server/api/session_control.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/murfey/server/api/session_control.py b/src/murfey/server/api/session_control.py index d376abf07..255cc0246 100644 --- a/src/murfey/server/api/session_control.py +++ b/src/murfey/server/api/session_control.py @@ -206,16 +206,20 @@ def count_number_of_movies(db=murfey_db) -> Dict[str, int]: class PostInfo(BaseModel): - url: str + router_name: str + function_name: str data: dict + kwargs: dict @router.post("/instruments/{instrument_name}/failed_client_post") def failed_client_post(instrument_name: str, post_info: PostInfo): zocalo_message = { "register": "failed_client_post", - "url": post_info.url, - "json": post_info.data, + "router_name": post_info.router_name, + "function_name": post_info.function_name, + "data": post_info.data, + "kwargs": post_info.kwargs, } if _transport_object: _transport_object.send(_transport_object.feedback_queue, zocalo_message) From d4573e182ddf3c6d3c0dd645e2437f6e96c5c093 Mon Sep 17 00:00:00 2001 From: yxd92326 Date: Thu, 4 Sep 2025 09:13:00 +0100 Subject: [PATCH 5/5] Make router names consistent --- src/murfey/server/api/session_info.py | 2 +- src/murfey/server/demo_api.py | 4 ++-- src/murfey/util/route_manifest.yaml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/murfey/server/api/session_info.py b/src/murfey/server/api/session_info.py index 474b8ae89..c96f54812 100644 --- a/src/murfey/server/api/session_info.py +++ b/src/murfey/server/api/session_info.py @@ -162,7 +162,7 @@ class VisitEndTime(BaseModel): end_time: Optional[datetime] = None -@router.post("/instruments/{instrument_name}/visits/{visit}/session/{name}") +@router.post("/instruments/{instrument_name}/visits/{visit}/sessions/{name}") def create_session( instrument_name: MurfeyInstrumentName, visit: str, diff --git a/src/murfey/server/demo_api.py b/src/murfey/server/demo_api.py index 3328d7346..c9fa3ba7d 100644 --- a/src/murfey/server/demo_api.py +++ b/src/murfey/server/demo_api.py @@ -228,7 +228,7 @@ class SessionClients(BaseModel): clients: List[ClientEnvironment] -@router.get("/session/{session_id}") +@router.get("/sessions/{session_id}") async def get_session(session_id: MurfeySessionID, db=murfey_db) -> SessionClients: session = db.exec(select(Session).where(Session.id == session_id)).one() clients = db.exec( @@ -996,7 +996,7 @@ async def get_tiff(visit_name: str, session_id: int, tiff_path: str, db=murfey_d return FileResponse(path=test_path) -@router.post("/instruments/{instrument_name}/visits/{visit}/session/{name}") +@router.post("/instruments/{instrument_name}/visits/{visit}/sessions/{name}") def create_session(instrument_name: str, visit: str, name: str, db=murfey_db) -> int: s = Session(name=name, visit=visit, instrument_name=instrument_name) db.add(s) diff --git a/src/murfey/util/route_manifest.yaml b/src/murfey/util/route_manifest.yaml index 79de069e5..86cf1179f 100644 --- a/src/murfey/util/route_manifest.yaml +++ b/src/murfey/util/route_manifest.yaml @@ -1047,7 +1047,7 @@ murfey.server.api.session_info.router: path_params: [] methods: - GET - - path: /session_info/instruments/{instrument_name}/visits/{visit}/session/{name} + - path: /session_info/instruments/{instrument_name}/visits/{visit}/sessions/{name} function: create_session path_params: - name: visit