Skip to content

Commit 0be4374

Browse files
committed
🎨 adds memory cache to get_service
1 parent 15efb0b commit 0be4374

File tree

4 files changed

+54
-11
lines changed

4 files changed

+54
-11
lines changed

services/web/server/src/simcore_service_webserver/catalog/_catalog_rest_client_service.py

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22

33
import logging
44
import urllib.parse
5-
from collections.abc import Iterator
5+
from collections.abc import Callable, Iterator
66
from contextlib import contextmanager
7-
from typing import Any
7+
from typing import Any, Final
88

9+
from aiocache import Cache, cached # type: ignore[import-untyped]
910
from aiohttp import ClientSession, ClientTimeout, web
1011
from aiohttp.client_exceptions import (
1112
ClientConnectionError,
@@ -15,7 +16,9 @@
1516
from models_library.api_schemas_catalog.service_access_rights import (
1617
ServiceAccessRightsGet,
1718
)
19+
from models_library.products import ProductName
1820
from models_library.services_resources import ServiceResourcesDict
21+
from models_library.services_types import ServiceKey, ServiceVersion
1922
from models_library.users import UserID
2023
from pydantic import TypeAdapter
2124
from servicelib.aiohttp import status
@@ -29,6 +32,16 @@
2932

3033
_logger = logging.getLogger(__name__)
3134

35+
# Cache settings
36+
_SECOND = 1 # in seconds
37+
_MINUTE = 60 * _SECOND
38+
_CACHE_TTL: Final = 1 * _MINUTE
39+
40+
41+
def _hash_service(_f: Callable[..., Any], *_args, **kw):
42+
assert len(_args) == 1, f"Expected only app, got {_args}" # nosec
43+
return f"get_service_{kw['user_id']}_{kw['service_key']}_{kw['service_version']}_{kw['product_name']}"
44+
3245

3346
@contextmanager
3447
def _handle_client_exceptions(app: web.Application) -> Iterator[ClientSession]:
@@ -103,12 +116,18 @@ async def get_services_for_user_in_product(
103116
return body
104117

105118

119+
@cached(
120+
ttl=_CACHE_TTL,
121+
key_builder=_hash_service,
122+
cache=Cache.MEMORY,
123+
)
106124
async def get_service(
107125
app: web.Application,
126+
*,
108127
user_id: UserID,
109-
service_key: str,
110-
service_version: str,
111-
product_name: str,
128+
service_key: ServiceKey,
129+
service_version: ServiceVersion,
130+
product_name: ProductName,
112131
) -> dict[str, Any]:
113132
settings: CatalogSettings = get_plugin_settings(app)
114133
url = URL(

services/web/server/src/simcore_service_webserver/catalog/_service.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,11 @@ async def list_service_inputs(
173173
service_key: ServiceKey, service_version: ServiceVersion, ctx: CatalogRequestContext
174174
) -> list[ServiceInputGet]:
175175
service = await _catalog_rest_client_service.get_service(
176-
ctx.app, ctx.user_id, service_key, service_version, ctx.product_name
176+
ctx.app,
177+
user_id=ctx.user_id,
178+
service_key=service_key,
179+
service_version=service_version,
180+
product_name=ctx.product_name,
177181
)
178182
return [
179183
await ServiceInputGetFactory.from_catalog_service_api_model(
@@ -190,7 +194,11 @@ async def get_service_input(
190194
ctx: CatalogRequestContext,
191195
) -> ServiceInputGet:
192196
service = await _catalog_rest_client_service.get_service(
193-
ctx.app, ctx.user_id, service_key, service_version, ctx.product_name
197+
ctx.app,
198+
user_id=ctx.user_id,
199+
service_key=service_key,
200+
service_version=service_version,
201+
product_name=ctx.product_name,
194202
)
195203
service_input: ServiceInputGet = (
196204
await ServiceInputGetFactory.from_catalog_service_api_model(
@@ -249,7 +257,11 @@ async def list_service_outputs(
249257
ctx: CatalogRequestContext,
250258
) -> list[ServiceOutputGet]:
251259
service = await _catalog_rest_client_service.get_service(
252-
ctx.app, ctx.user_id, service_key, service_version, ctx.product_name
260+
ctx.app,
261+
user_id=ctx.user_id,
262+
service_key=service_key,
263+
service_version=service_version,
264+
product_name=ctx.product_name,
253265
)
254266
return [
255267
await ServiceOutputGetFactory.from_catalog_service_api_model(
@@ -266,7 +278,11 @@ async def get_service_output(
266278
ctx: CatalogRequestContext,
267279
) -> ServiceOutputGet:
268280
service = await _catalog_rest_client_service.get_service(
269-
ctx.app, ctx.user_id, service_key, service_version, ctx.product_name
281+
ctx.app,
282+
user_id=ctx.user_id,
283+
service_key=service_key,
284+
service_version=service_version,
285+
product_name=ctx.product_name,
270286
)
271287
return cast( # mypy -> aiocache is not typed.
272288
ServiceOutputGet,

services/web/server/src/simcore_service_webserver/projects/_projects_service.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1682,7 +1682,11 @@ async def is_service_deprecated(
16821682
product_name: str,
16831683
) -> bool:
16841684
service = await catalog_service.get_service(
1685-
app, user_id, service_key, service_version, product_name
1685+
app,
1686+
user_id=user_id,
1687+
service_key=service_key,
1688+
service_version=service_version,
1689+
product_name=product_name,
16861690
)
16871691
if deprecation_date := service.get("deprecated"):
16881692
deprecation_date_bool: bool = datetime.datetime.now(

services/web/server/src/simcore_service_webserver/resource_usage/_pricing_plans_admin_service.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,11 @@ async def connect_service_to_pricing_plan(
164164
) -> PricingPlanToServiceGet:
165165
# Check whether service key and version exists
166166
await catalog_service.get_service(
167-
app, user_id, service_key, service_version, product_name
167+
app,
168+
user_id=user_id,
169+
service_key=service_key,
170+
service_version=service_version,
171+
product_name=product_name,
168172
)
169173

170174
rpc_client = get_rabbitmq_rpc_client(app)

0 commit comments

Comments
 (0)