Skip to content

Commit 3bce414

Browse files
authored
BugFix: fixes awaitables and broad-exceptions in garbage-collector (#2104)
* Missing await * Global exceptions were silencing CancellationError * Catches all db errors * Fixes typing and imports * Fixes group_id str type and disables delete user mock * Fixes typing and closes result * Adapted gid type
1 parent 5b03724 commit 3bce414

File tree

9 files changed

+133
-89
lines changed

9 files changed

+133
-89
lines changed

packages/postgres-database/tests/test_groups.py

+19-4
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
11
# pylint: disable=no-name-in-module
22
# pylint: disable=no-value-for-parameter
33

4-
import pytest
5-
from aiopg.sa.result import RowProxy
6-
from psycopg2.errors import ForeignKeyViolation, RaiseException, UniqueViolation
7-
from sqlalchemy import literal_column
84

5+
from typing import Optional
6+
7+
import aiopg.sa.exc
8+
import pytest
9+
from aiopg.sa.result import ResultProxy, RowProxy
910
from fake_creators import random_group, random_user
11+
from psycopg2.errors import ForeignKeyViolation, RaiseException, UniqueViolation
1012
from simcore_postgres_database.models.base import metadata
1113
from simcore_postgres_database.webserver_models import (
1214
GroupType,
1315
groups,
1416
user_to_groups,
1517
users,
1618
)
19+
from sqlalchemy import literal_column
1720

1821

1922
async def _create_group(conn, **overrides) -> RowProxy:
@@ -41,6 +44,7 @@ async def test_user_group_uniqueness(make_engine):
4144
sync_engine = make_engine(False)
4245
metadata.drop_all(sync_engine)
4346
metadata.create_all(sync_engine)
47+
4448
async with engine.acquire() as conn:
4549
rory_group = await _create_group(conn, name="Rory Storm and the Hurricanes")
4650
ringo = await _create_user(conn, "Ringo", rory_group)
@@ -50,6 +54,17 @@ async def test_user_group_uniqueness(make_engine):
5054
user_to_groups.insert().values(uid=ringo.id, gid=rory_group.gid)
5155
)
5256

57+
# Checks implementation of simcore_service_webserver/groups_api.py:get_group_from_gid
58+
res: ResultProxy = await conn.execute(
59+
groups.select().where(groups.c.gid == rory_group.gid)
60+
)
61+
62+
the_one: Optional[RowProxy] = await res.first()
63+
assert the_one.type == the_one["type"]
64+
65+
with pytest.raises(aiopg.sa.exc.ResourceClosedError):
66+
await res.fetchone()
67+
5368

5469
async def test_all_group(make_engine):
5570
engine = await make_engine()

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

+14-8
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
""" Extends assertions for testing
22
33
"""
4-
from aiohttp import web
5-
64
from pprint import pformat
5+
from typing import Type
6+
7+
from aiohttp import ClientResponse
8+
from aiohttp.web import HTTPError, HTTPException, HTTPInternalServerError, HTTPNoContent
79
from servicelib.rest_responses import unwrap_envelope
810

911

1012
async def assert_status(
11-
response: web.Response, expected_cls: web.HTTPException, expected_msg: str = None
13+
response: ClientResponse,
14+
expected_cls: Type[HTTPException],
15+
expected_msg: str = None,
1216
):
1317
"""
1418
Asserts for enveloped responses
@@ -18,10 +22,10 @@ async def assert_status(
1822
response.status == expected_cls.status_code
1923
), f"received: ({data},{error}), \nexpected ({expected_cls.status_code}, {expected_msg})"
2024

21-
if issubclass(expected_cls, web.HTTPError):
25+
if issubclass(expected_cls, HTTPError):
2226
do_assert_error(data, error, expected_cls, expected_msg)
2327

24-
elif issubclass(expected_cls, web.HTTPNoContent):
28+
elif issubclass(expected_cls, HTTPNoContent):
2529
assert not data, pformat(data)
2630
assert not error, pformat(error)
2731
else:
@@ -37,14 +41,16 @@ async def assert_status(
3741

3842

3943
async def assert_error(
40-
response: web.Response, expected_cls: web.HTTPException, expected_msg: str = None
44+
response: ClientResponse,
45+
expected_cls: Type[HTTPException],
46+
expected_msg: str = None,
4147
):
4248
data, error = unwrap_envelope(await response.json())
4349
return do_assert_error(data, error, expected_cls, expected_msg)
4450

4551

4652
def do_assert_error(
47-
data, error, expected_cls: web.HTTPException, expected_msg: str = None
53+
data, error, expected_cls: Type[HTTPException], expected_msg: str = None
4854
):
4955
assert not data, pformat(data)
5056
assert error, pformat(error)
@@ -55,7 +61,7 @@ def do_assert_error(
5561
if expected_msg:
5662
assert expected_msg in err["message"]
5763

58-
if expected_cls != web.HTTPInternalServerError:
64+
if expected_cls != HTTPInternalServerError:
5965
# otherwise, code is exactly the name of the Exception class
6066
assert expected_cls.__name__ == err["code"]
6167

services/sidecar/src/simcore_service_sidecar/log_parser.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ async def _monitor_log_file(
121121
# try to read line
122122
line = await file_pointer.readline()
123123
if not line:
124-
asyncio.sleep(1)
124+
await asyncio.sleep(1)
125125
continue
126126
log_type, parsed_line = await parse_line(line)
127127

services/web/server/src/simcore_service_webserver/groups_api.py

+8-5
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
import sqlalchemy as sa
66
from aiohttp import web
77
from aiopg.sa import SAConnection
8-
from aiopg.sa.result import RowProxy
8+
from aiopg.sa.engine import Engine
9+
from aiopg.sa.result import ResultProxy, RowProxy
910
from servicelib.application_keys import APP_DB_ENGINE_KEY
1011
from sqlalchemy import and_, literal_column
1112
from sqlalchemy.dialects.postgresql import insert
@@ -348,9 +349,11 @@ async def delete_user_in_group(
348349
)
349350

350351

351-
async def get_group_from_gid(app: web.Application, gid: int) -> Dict:
352-
engine = app[APP_DB_ENGINE_KEY]
352+
async def get_group_from_gid(app: web.Application, gid: int) -> Optional[RowProxy]:
353+
engine: Engine = app[APP_DB_ENGINE_KEY]
353354

354355
async with engine.acquire() as conn:
355-
group = await conn.execute(sa.select([groups]).where(groups.c.gid == gid))
356-
return await group.fetchone()
356+
res: ResultProxy = await conn.execute(
357+
groups.select().where(groups.c.gid == gid)
358+
)
359+
return await res.first()

services/web/server/src/simcore_service_webserver/resource_manager/config.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,15 @@
77

88
import trafaret as T
99
from aiohttp.web import Application
10-
from pydantic import BaseSettings, Field, PositiveInt
11-
1210
from models_library.settings.redis import RedisConfig
11+
from pydantic import BaseSettings, Field, PositiveInt
1312
from servicelib.application_keys import APP_CONFIG_KEY
1413

1514
CONFIG_SECTION_NAME = "resource_manager"
1615
APP_CLIENT_REDIS_CLIENT_KEY = __name__ + ".resource_manager.redis_client"
1716
APP_CLIENT_REDIS_LOCK_KEY = __name__ + ".resource_manager.redis_lock"
1817
APP_CLIENT_SOCKET_REGISTRY_KEY = __name__ + ".resource_manager.registry"
1918
APP_RESOURCE_MANAGER_TASKS_KEY = __name__ + ".resource_manager.tasks.key"
20-
APP_GARBAGE_COLLECTOR_KEY = __name__ + ".resource_manager.garbage_collector_key"
2119

2220

2321
# lock names and format strings

0 commit comments

Comments
 (0)