Skip to content

Commit 58f9862

Browse files
authored
♻️ Refactor: migrate more aiohttp app keys to type-safe web.AppKey (#8424)
1 parent 1dbb64b commit 58f9862

File tree

114 files changed

+515
-406
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

114 files changed

+515
-406
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
mode: edit
3+
description: Converts string-based aiohttp app key constants to type-safe web.AppKey
4+
model: GPT-4.1
5+
---
6+
7+
Convert all string-based app key constants to use type-safe web.AppKey.
8+
9+
- Replace patterns like:
10+
```python
11+
CONSTNAME_APPKEY: Final[str] = f"{__name__}.my_key"
12+
```
13+
with:
14+
```python
15+
from aiohttp import web
16+
CONSTNAME_APPKEY: Final = web.AppKey("CONSTNAME", ValueType)
17+
```
18+
(Replace ValueType with the actual type stored under this key.)
19+
20+
- Update all usages:
21+
- `app[CONSTNAME_APPKEY] = value`
22+
- `data = app[CONSTNAME_APPKEY]` or `data = request.app[CONSTNAME_APPKEY]`
23+
24+
- Key constant MUST be UPPERCASE
25+
- Key name MUST be suffixed `_APPKEY`
26+
- Remove any f"{__name__}..." patterns; use a simple string identifier in web.AppKey.
27+
- Ensure all keys are type-safe and self-documenting.
28+
- IF you change the original name, you MUST change all the references
File renamed without changes.

packages/pytest-simcore/src/pytest_simcore/helpers/webserver_projects.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
update_or_insert_project_group,
1818
)
1919
from simcore_service_webserver.projects._projects_repository_legacy import (
20-
APP_PROJECT_DBAPI,
20+
PROJECT_DBAPI_APPKEY,
2121
ProjectDBAPI,
2222
)
2323
from simcore_service_webserver.projects._projects_repository_legacy_utils import (
@@ -71,7 +71,7 @@ async def create_project(
7171

7272
project_data.update(params_override)
7373

74-
db: ProjectDBAPI = app[APP_PROJECT_DBAPI]
74+
db: ProjectDBAPI = app[PROJECT_DBAPI_APPKEY]
7575

7676
new_project = await db.insert_project(
7777
project_data,
@@ -131,7 +131,7 @@ async def create_project(
131131
async def delete_all_projects(app: web.Application):
132132
from simcore_postgres_database.webserver_models import projects
133133

134-
db = app[APP_PROJECT_DBAPI]
134+
db = app[PROJECT_DBAPI_APPKEY]
135135
async with db.engine.acquire() as conn:
136136
query = projects.delete()
137137
await conn.execute(query)

packages/service-library/src/servicelib/aiohttp/application.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ async def _first_call_on_cleanup(app: web.Application):
2323

2424

2525
async def _cancel_all_fire_and_forget_registered_tasks(app: web.Application):
26-
registered_tasks: set[asyncio.Task] = app[APP_FIRE_AND_FORGET_TASKS_KEY]
26+
registered_tasks = app[APP_FIRE_AND_FORGET_TASKS_KEY]
2727
for task in registered_tasks:
2828
task.cancel()
2929

@@ -37,7 +37,7 @@ async def _cancel_all_fire_and_forget_registered_tasks(app: web.Application):
3737
"Following observation tasks completed with an unexpected error:%s",
3838
f"{bad_results}",
3939
)
40-
except asyncio.TimeoutError:
40+
except TimeoutError:
4141
_logger.exception(
4242
"Timed-out waiting more than %s secs for %s to complete. Action: Check why this is blocking",
4343
_MAX_WAIT_TIME_TO_CANCEL_SECONDS,

packages/service-library/src/servicelib/aiohttp/application_keys.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
See https://aiohttp.readthedocs.io/en/stable/web_advanced.html#data-sharing-aka-no-singletons-please
1010
"""
1111

12+
import asyncio
1213
from typing import Final
1314

1415
from aiohttp import ClientSession, web
@@ -21,17 +22,17 @@
2122
#
2223
# web.Application keys, i.e. app[APP_*_KEY]
2324
#
24-
APP_CONFIG_KEY = web.AppKey("APP_CONFIG_KEY", dict[str, object])
25+
APP_CONFIG_KEY: Final = web.AppKey("APP_CONFIG_KEY", dict[str, object])
2526

2627
APP_AIOPG_ENGINE_KEY: Final[str] = f"{__name__ }.aiopg_engine"
2728

28-
APP_CLIENT_SESSION_KEY: web.AppKey[ClientSession] = web.AppKey("APP_CLIENT_SESSION_KEY")
29+
APP_CLIENT_SESSION_KEY: Final = web.AppKey("APP_CLIENT_SESSION_KEY", ClientSession)
2930

3031

31-
APP_FIRE_AND_FORGET_TASKS_KEY: Final[str] = f"{__name__}.tasks"
32+
APP_FIRE_AND_FORGET_TASKS_KEY: Final = web.AppKey(
33+
"APP_FIRE_AND_FORGET_TASKS_KEY", set[asyncio.Task]
34+
)
3235

33-
APP_RABBITMQ_CLIENT_KEY: Final[str] = f"{__name__}.rabbit_client"
34-
APP_RABBITMQ_RPC_SERVER_KEY: Final[str] = f"{__name__}.rabbit_rpc_server"
3536

3637
#
3738
# web.Response keys, i.e. app[RSP_*_KEY]

packages/service-library/src/servicelib/aiohttp/monitor_services.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from enum import Enum
2+
from typing import Final
23

34
from aiohttp import web
45
from prometheus_client import Counter
@@ -22,8 +23,8 @@
2223
#
2324

2425

25-
MONITOR_SERVICE_STARTED = f"{__name__}.services_started"
26-
MONITOR_SERVICE_STOPPED = f"{__name__}.services_stopped"
26+
MONITOR_SERVICE_STARTED_APPKEY: Final = web.AppKey("MONITOR_SERVICE_STARTED", Counter)
27+
MONITOR_SERVICE_STOPPED_APPKEY: Final = web.AppKey("MONITOR_SERVICE_STOPPED", Counter)
2728

2829
MONITOR_SERVICE_STARTED_LABELS: list[str] = [
2930
"service_key",
@@ -42,7 +43,7 @@
4243
def add_instrumentation(
4344
app: web.Application, reg: CollectorRegistry, app_name: str
4445
) -> None:
45-
app[MONITOR_SERVICE_STARTED] = Counter(
46+
app[MONITOR_SERVICE_STARTED_APPKEY] = Counter(
4647
name="services_started_total",
4748
documentation="Counts the services started",
4849
labelnames=MONITOR_SERVICE_STARTED_LABELS,
@@ -51,7 +52,7 @@ def add_instrumentation(
5152
registry=reg,
5253
)
5354

54-
app[MONITOR_SERVICE_STOPPED] = Counter(
55+
app[MONITOR_SERVICE_STOPPED_APPKEY] = Counter(
5556
name="services_stopped_total",
5657
documentation="Counts the services stopped",
5758
labelnames=MONITOR_SERVICE_STOPPED_LABELS,
@@ -73,7 +74,7 @@ def service_started(
7374
service_tag: str,
7475
simcore_user_agent: str,
7576
) -> None:
76-
app[MONITOR_SERVICE_STARTED].labels(
77+
app[MONITOR_SERVICE_STARTED_APPKEY].labels(
7778
service_key=service_key,
7879
service_tag=service_tag,
7980
simcore_user_agent=simcore_user_agent,
@@ -88,7 +89,7 @@ def service_stopped(
8889
simcore_user_agent: str,
8990
result: ServiceResult | str,
9091
) -> None:
91-
app[MONITOR_SERVICE_STOPPED].labels(
92+
app[MONITOR_SERVICE_STOPPED_APPKEY].labels(
9293
service_key=service_key,
9394
service_tag=service_tag,
9495
simcore_user_agent=simcore_user_agent,

packages/service-library/src/servicelib/aiohttp/monitoring.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@
2727

2828
_logger = logging.getLogger(__name__)
2929

30-
_PROMETHEUS_METRICS: Final[str] = f"{__name__}.prometheus_metrics" # noqa: N816
31-
APP_MONITORING_NAMESPACE_KEY: Final = web.AppKey("APP_MONITORING_NAMESPACE_KEY", str)
30+
PROMETHEUS_METRICS_APPKEY: Final = web.AppKey("PROMETHEUS_METRICS", PrometheusMetrics)
31+
MONITORING_NAMESPACE_APPKEY: Final = web.AppKey("APP_MONITORING_NAMESPACE_KEY", str)
3232

3333

3434
def get_collector_registry(app: web.Application) -> CollectorRegistry:
35-
metrics = app[_PROMETHEUS_METRICS]
35+
metrics = app[PROMETHEUS_METRICS_APPKEY]
3636
assert isinstance(metrics, PrometheusMetrics) # nosec
3737
return metrics.registry
3838

@@ -71,7 +71,7 @@ async def middleware_handler(request: web.Request, handler: Handler):
7171
with log_catch(logger=_logger, reraise=False):
7272
await enter_middleware_cb(request)
7373

74-
metrics = request.app[_PROMETHEUS_METRICS]
74+
metrics = request.app[PROMETHEUS_METRICS_APPKEY]
7575
assert isinstance(metrics, PrometheusMetrics) # nosec
7676

7777
user_agent = request.headers.get(
@@ -130,7 +130,7 @@ def setup_monitoring(
130130
enter_middleware_cb: EnterMiddlewareCB | None = None,
131131
exit_middleware_cb: ExitMiddlewareCB | None = None,
132132
):
133-
app[_PROMETHEUS_METRICS] = get_prometheus_metrics()
133+
app[PROMETHEUS_METRICS_APPKEY] = get_prometheus_metrics()
134134

135135
# WARNING: ensure ERROR middleware is over this one
136136
#

packages/service-library/src/servicelib/aiohttp/observer.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,8 @@
1616
log = logging.getLogger(__name__)
1717

1818

19-
_APP_OBSERVER_EVENTS_REGISTRY_KEY = "{__name__}.event_registry"
20-
APP_FIRE_AND_FORGET_TASKS_KEY: Final = web.AppKey(
21-
"APP_FIRE_AND_FORGET_TASKS_KEY", set[object]
19+
_APP_OBSERVER_EVENTS_REGISTRY_APPKEY: Final = web.AppKey(
20+
"APP_OBSERVER_EVENTS_REGISTRY", defaultdict
2221
)
2322

2423

@@ -28,12 +27,12 @@ class ObserverRegistryNotFoundError(RuntimeError): ...
2827
@ensure_single_setup(__name__, logger=log)
2928
def setup_observer_registry(app: web.Application):
3029
# only once
31-
app.setdefault(_APP_OBSERVER_EVENTS_REGISTRY_KEY, defaultdict(list))
30+
app.setdefault(_APP_OBSERVER_EVENTS_REGISTRY_APPKEY, defaultdict(list))
3231

3332

3433
def _get_registry(app: web.Application) -> defaultdict:
3534
try:
36-
registry: defaultdict = app[_APP_OBSERVER_EVENTS_REGISTRY_KEY]
35+
registry: defaultdict = app[_APP_OBSERVER_EVENTS_REGISTRY_APPKEY]
3736
return registry
3837
except KeyError as err:
3938
msg = "Could not find observer registry. TIP: initialize app with setup_observer_registry"
@@ -49,7 +48,7 @@ def register_observer(app: web.Application, func: Callable, event: str):
4948

5049

5150
def registed_observers_report(app: web.Application) -> str:
52-
if _event_registry := app.get(_APP_OBSERVER_EVENTS_REGISTRY_KEY):
51+
if _event_registry := app.get(_APP_OBSERVER_EVENTS_REGISTRY_APPKEY):
5352
return "\n".join(
5453
f" {event}->{len(funcs)} handles"
5554
for event, funcs in _event_registry.items()
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
from aiohttp import web
22
from settings_library.prometheus import PrometheusSettings
33

4-
from ..constants import APP_SETTINGS_KEY
4+
from ..application_keys import APP_SETTINGS_APPKEY
55

66

77
def get_plugin_settings(app: web.Application) -> PrometheusSettings:
8-
settings: PrometheusSettings | None = app[APP_SETTINGS_KEY].WEBSERVER_ACTIVITY
8+
settings: PrometheusSettings | None = app[APP_SETTINGS_APPKEY].WEBSERVER_ACTIVITY
99
assert settings, "setup_settings not called?" # nosec
1010
assert isinstance(settings, PrometheusSettings) # nosec
1111
return settings

services/web/server/src/simcore_service_webserver/announcements/plugin.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66

77
from aiohttp import web
88

9+
from ..application_keys import APP_SETTINGS_APPKEY
910
from ..application_setup import ModuleCategory, app_setup_func
10-
from ..constants import APP_SETTINGS_KEY
1111
from ..products.plugin import setup_products
1212
from ..redis import setup_redis
1313
from . import _handlers
@@ -22,7 +22,7 @@
2222
logger=_logger,
2323
)
2424
def setup_announcements(app: web.Application):
25-
assert app[APP_SETTINGS_KEY].WEBSERVER_ANNOUNCEMENTS # nosec
25+
assert app[APP_SETTINGS_APPKEY].WEBSERVER_ANNOUNCEMENTS # nosec
2626

2727
setup_products(app)
2828
setup_redis(app)

0 commit comments

Comments
 (0)