Skip to content

Commit

Permalink
🐛Webserver: Improve slow synchronous calls (#4753)
Browse files Browse the repository at this point in the history
  • Loading branch information
sanderegg authored Sep 14, 2023
1 parent 063653b commit 6d223c8
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 17 deletions.
22 changes: 16 additions & 6 deletions services/web/server/src/simcore_service_webserver/catalog/_api.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import asyncio
import logging
from collections.abc import Iterator
from typing import Any
Expand Down Expand Up @@ -69,8 +70,11 @@ async def list_services(
)
for service in services:
try:
replace_service_input_outputs(
service, unit_registry=unit_registry, **RESPONSE_MODEL_POLICY
await asyncio.to_thread(
replace_service_input_outputs,
service,
unit_registry=unit_registry,
**RESPONSE_MODEL_POLICY,
)
except KeyError: # noqa: PERF203
# This will limit the effect of a any error in the formatting of
Expand All @@ -93,8 +97,11 @@ async def get_service(
service = await client.get_service(
ctx.app, ctx.user_id, service_key, service_version, ctx.product_name
)
replace_service_input_outputs(
service, unit_registry=ctx.unit_registry, **RESPONSE_MODEL_POLICY
await asyncio.to_thread(
replace_service_input_outputs,
service,
unit_registry=ctx.unit_registry,
**RESPONSE_MODEL_POLICY,
)
return service

Expand All @@ -113,8 +120,11 @@ async def update_service(
ctx.product_name,
update_data,
)
replace_service_input_outputs(
service, unit_registry=ctx.unit_registry, **RESPONSE_MODEL_POLICY
await asyncio.to_thread(
replace_service_input_outputs,
service,
unit_registry=ctx.unit_registry,
**RESPONSE_MODEL_POLICY,
)
return service

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
should live in the catalog service in his final version
"""
import asyncio
import logging
import urllib.parse
from typing import Any, Final
Expand Down Expand Up @@ -76,7 +77,9 @@ async def list_services(request: Request):
# assert parse_obj_as(list[ServiceGet], data_array) is not None # nosec
#

return envelope_json_response(data_array)
return await asyncio.get_event_loop().run_in_executor(
None, envelope_json_response, data_array
)


@routes.get(
Expand All @@ -92,7 +95,9 @@ async def get_service(request: Request):
path_params.service_key, path_params.service_version, ctx
)
assert parse_obj_as(ServiceGet, data) is not None # nosec
return envelope_json_response(data)
return await asyncio.get_event_loop().run_in_executor(
None, envelope_json_response, data
)


@routes.patch(
Expand All @@ -117,7 +122,9 @@ async def update_service(request: Request):
)

assert parse_obj_as(ServiceGet, data) is not None # nosec
return envelope_json_response(data)
return await asyncio.get_event_loop().run_in_executor(
None, envelope_json_response, data
)


@routes.get(
Expand All @@ -136,7 +143,9 @@ async def list_service_inputs(request: Request):
)

data = [m.dict(**RESPONSE_MODEL_POLICY) for m in response_model]
return envelope_json_response(data)
return await asyncio.get_event_loop().run_in_executor(
None, envelope_json_response, data
)


class _ServiceInputsPathParams(ServicePathParams):
Expand All @@ -162,7 +171,9 @@ async def get_service_input(request: Request):
)

data = response_model.dict(**RESPONSE_MODEL_POLICY)
return envelope_json_response(data)
return await asyncio.get_event_loop().run_in_executor(
None, envelope_json_response, data
)


class _FromServiceOutputParams(BaseModel):
Expand Down Expand Up @@ -192,7 +203,9 @@ async def get_compatible_inputs_given_source_output(request: Request):
ctx,
)

return envelope_json_response(data)
return await asyncio.get_event_loop().run_in_executor(
None, envelope_json_response, data
)


@routes.get(
Expand All @@ -211,7 +224,9 @@ async def list_service_outputs(request: Request):
)

data = [m.dict(**RESPONSE_MODEL_POLICY) for m in response_model]
return envelope_json_response(data)
return await asyncio.get_event_loop().run_in_executor(
None, envelope_json_response, data
)


class _ServiceOutputsPathParams(ServicePathParams):
Expand All @@ -237,7 +252,9 @@ async def get_service_output(request: Request):
)

data = response_model.dict(**RESPONSE_MODEL_POLICY)
return envelope_json_response(data)
return await asyncio.get_event_loop().run_in_executor(
None, envelope_json_response, data
)


class _ToServiceInputsParams(BaseModel):
Expand Down Expand Up @@ -271,7 +288,9 @@ async def get_compatible_outputs_given_target_input(request: Request):
ctx,
)

return envelope_json_response(data)
return await asyncio.get_event_loop().run_in_executor(
None, envelope_json_response, data
)


@routes.get(
Expand All @@ -296,4 +315,6 @@ async def get_service_resources(request: Request):
)

data = ServiceResourcesDictHelpers.create_jsonable(service_resources)
return envelope_json_response(data)
return await asyncio.get_event_loop().run_in_executor(
None, envelope_json_response, data
)
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ def from_catalog_service_api_model(
if "defaultValue" in data:
data.pop("defaultValue")

port = ServiceOutputGet(key_id=output_key, **data) # validated
# NOTE: this call must be validated if port property type is "ref_contentSchema"
port = ServiceOutputGet(key_id=output_key, **data)

unit_html: UnitHtmlFormat | None
if ureg and (unit_html := get_html_formatted_unit(port, ureg)):
Expand Down

0 comments on commit 6d223c8

Please sign in to comment.