From fcd88fb3c6874f66b94020347d6989cd1592f010 Mon Sep 17 00:00:00 2001 From: guerler Date: Sat, 23 May 2026 00:28:24 +0300 Subject: [PATCH] Update job services --- lib/galaxy/webapps/galaxy/services/base.py | 33 ++++++++++++++++------ lib/galaxy/webapps/galaxy/services/jobs.py | 12 ++------ 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/lib/galaxy/webapps/galaxy/services/base.py b/lib/galaxy/webapps/galaxy/services/base.py index e8692496618..6b6e36abf19 100644 --- a/lib/galaxy/webapps/galaxy/services/base.py +++ b/lib/galaxy/webapps/galaxy/services/base.py @@ -1,3 +1,4 @@ +import logging import mimetypes from tempfile import NamedTemporaryFile from typing import ( @@ -46,6 +47,8 @@ from galaxy.tool_util.parameters.state import RequestInternalToolState from galaxy.tool_util.parser import get_tool_source from galaxy.util import ready_name_for_url +log = logging.getLogger(__name__) + def ensure_celery_tasks_enabled(config): if not config.enable_celery_tasks: @@ -183,17 +186,29 @@ class ConsumesModelStores: def _encode_tool_request(tool_request: ToolRequest, security: IdEncodingHelper) -> dict[str, Any]: - """Encode request IDs using strongly-typed parameter walking.""" + """Encode request IDs using strongly-typed parameter walking. + + Rows captured outside the async-API path (workflow tool steps) may have + a payload that does not satisfy the tool's strict typed model — legacy + ``.ga`` workflows store numeric params as strings, for instance. In that + case the strict walk would 400 the entire endpoint, blocking consumers + (e.g. the History Graph UI) that only need the structural shape. Fall + back to the raw payload so the endpoint stays usable. + """ tool_source_model = tool_request.tool_source raw_tool_source = cast(str, tool_source_model.source) - parsed_tool_source = get_tool_source( - tool_source_class=tool_source_model.source_class, - raw_tool_source=raw_tool_source, - ) - parameter_bundle = input_models_for_tool_source(parsed_tool_source) - internal_state = RequestInternalToolState(tool_request.request) - encoded_state = encode_request(internal_state, parameter_bundle, security.encode_id) - return encoded_state.input_state + try: + parsed_tool_source = get_tool_source( + tool_source_class=tool_source_model.source_class, + raw_tool_source=raw_tool_source, + ) + parameter_bundle = input_models_for_tool_source(parsed_tool_source) + internal_state = RequestInternalToolState(tool_request.request) + encoded_state = encode_request(internal_state, parameter_bundle, security.encode_id) + return encoded_state.input_state + except Exception as e: + log.debug("Falling back to raw payload for tool_request %d: %s", tool_request.id, e) + return tool_request.request if isinstance(tool_request.request, dict) else {} def tool_request_to_model(tool_request: ToolRequest, security: IdEncodingHelper) -> ToolRequestModel: diff --git a/lib/galaxy/webapps/galaxy/services/jobs.py b/lib/galaxy/webapps/galaxy/services/jobs.py index 9e8cc7dada8..790b5d5a196 100644 --- a/lib/galaxy/webapps/galaxy/services/jobs.py +++ b/lib/galaxy/webapps/galaxy/services/jobs.py @@ -30,11 +30,11 @@ from galaxy.managers.jobs import ( JobSearch, view_show_job, ) +from galaxy.managers.tool_source import get_or_create_tool_source from galaxy.managers.tools import ToolRunReference from galaxy.model import ( Job, ToolRequest, - ToolSource as ToolSourceModel, ) from galaxy.schema.fields import ( DecodedDatabaseIdField, @@ -262,19 +262,13 @@ class JobsService(ServiceBase): request_state = RequestToolState(inputs or {}) request_state.validate(parameter_bundle, f"{tool.id} (request model)") request_internal_state = decode(request_state, parameter_bundle, trans.security.decode_id) + sa_session = trans.sa_session + tool_source_model = get_or_create_tool_source(sa_session, tool) tool_request = ToolRequest() - # TODO: hash and such... - tool_source_model = ToolSourceModel( - source=tool.tool_source.to_string(), - source_class=type(tool.tool_source).__name__, - hash="TODO", - ) tool_request.request = request_internal_state.input_state tool_request.tool_source = tool_source_model tool_request.state = ToolRequest.states.NEW tool_request.history = target_history - sa_session = trans.sa_session - sa_session.add(tool_source_model) sa_session.add(tool_request) sa_session.commit() tool_request_id = tool_request.id