Skip to content

Commit a1bec4b

Browse files
committed
merge msater into 6704-instrument-httpx-clients
2 parents 285bfc1 + d9fb9d2 commit a1bec4b

File tree

51 files changed

+1195
-683
lines changed

Some content is hidden

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

51 files changed

+1195
-683
lines changed

api/specs/web-server/_folders.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,28 @@ async def list_folders(
6363
...
6464

6565

66+
@router.get(
67+
"/folders:search",
68+
response_model=Envelope[list[FolderGet]],
69+
)
70+
async def list_folders_full_search(
71+
params: Annotated[PageQueryParameters, Depends()],
72+
text: str | None = None,
73+
order_by: Annotated[
74+
Json,
75+
Query(
76+
description="Order by field (modified_at|name|description) and direction (asc|desc). The default sorting order is ascending.",
77+
example='{"field": "name", "direction": "desc"}',
78+
),
79+
] = '{"field": "modified_at", "direction": "desc"}',
80+
filters: Annotated[
81+
Json | None,
82+
Query(description=FolderFilters.schema_json(indent=1)),
83+
] = None,
84+
):
85+
...
86+
87+
6688
@router.get(
6789
"/folders/{folder_id}",
6890
response_model=Envelope[FolderGet],

packages/models-library/src/models_library/folders.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
from pydantic import BaseModel, Field, PositiveInt, validator
66

7+
from .access_rights import AccessRights
78
from .users import GroupID, UserID
89
from .utils.enums import StrAutoEnum
910
from .workspaces import WorkspaceID
@@ -66,3 +67,10 @@ class FolderDB(BaseModel):
6667

6768
class Config:
6869
orm_mode = True
70+
71+
72+
class UserFolderAccessRightsDB(FolderDB):
73+
my_access_rights: AccessRights
74+
75+
class Config:
76+
orm_mode = True
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
def assemble_array_groups(user_group_ids: list[int]) -> str:
2+
return (
3+
"array[]::text[]"
4+
if len(user_group_ids) == 0
5+
else f"""array[{', '.join(f"'{group_id}'" for group_id in user_group_ids)}]"""
6+
)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from simcore_postgres_database.models.groups import user_to_groups
2+
from simcore_postgres_database.models.workspaces_access_rights import (
3+
workspaces_access_rights,
4+
)
5+
from sqlalchemy import func
6+
from sqlalchemy.dialects.postgresql import BOOLEAN, INTEGER
7+
from sqlalchemy.sql import Subquery, select
8+
9+
10+
def create_my_workspace_access_rights_subquery(user_id: int) -> Subquery:
11+
return (
12+
select(
13+
workspaces_access_rights.c.workspace_id,
14+
func.json_build_object(
15+
"read",
16+
func.max(workspaces_access_rights.c.read.cast(INTEGER)).cast(BOOLEAN),
17+
"write",
18+
func.max(workspaces_access_rights.c.write.cast(INTEGER)).cast(BOOLEAN),
19+
"delete",
20+
func.max(workspaces_access_rights.c.delete.cast(INTEGER)).cast(BOOLEAN),
21+
).label("my_access_rights"),
22+
)
23+
.select_from(
24+
workspaces_access_rights.join(
25+
user_to_groups, user_to_groups.c.gid == workspaces_access_rights.c.gid
26+
)
27+
)
28+
.where(user_to_groups.c.uid == user_id)
29+
.group_by(workspaces_access_rights.c.workspace_id)
30+
).subquery("my_workspace_access_rights_subquery")

packages/service-library/src/servicelib/redis.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ async def _cancel_or_warn(task: Task) -> None:
6060
@dataclass
6161
class RedisClientSDK:
6262
redis_dsn: str
63+
client_name: str
6364
decode_responses: bool = _DEFAULT_DECODE_RESPONSES
6465
health_check_interval: datetime.timedelta = _DEFAULT_HEALTH_CHECK_INTERVAL
6566

@@ -86,7 +87,7 @@ def __post_init__(self):
8687
socket_connect_timeout=_DEFAULT_SOCKET_TIMEOUT.total_seconds(),
8788
encoding="utf-8",
8889
decode_responses=self.decode_responses,
89-
auto_close_connection_pool=True,
90+
client_name=self.client_name,
9091
)
9192

9293
@retry(**RedisRetryPolicyUponInitialization(_logger).kwargs)
@@ -238,6 +239,7 @@ class RedisClientsManager:
238239

239240
databases_configs: set[RedisManagerDBConfig]
240241
settings: RedisSettings
242+
client_name: str
241243

242244
_client_sdks: dict[RedisDatabase, RedisClientSDK] = field(default_factory=dict)
243245

@@ -247,6 +249,7 @@ async def setup(self) -> None:
247249
redis_dsn=self.settings.build_redis_dsn(config.database),
248250
decode_responses=config.decode_responses,
249251
health_check_interval=config.health_check_interval,
252+
client_name=f"{self.client_name}",
250253
)
251254

252255
for client in self._client_sdks.values():

packages/service-library/tests/conftest.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,12 @@ async def _(
8080
database: RedisDatabase, decode_response: bool = True # noqa: FBT002
8181
) -> AsyncIterator[RedisClientSDK]:
8282
redis_resources_dns = redis_service.build_redis_dsn(database)
83-
client = RedisClientSDK(redis_resources_dns, decode_responses=decode_response)
83+
client = RedisClientSDK(
84+
redis_resources_dns, decode_responses=decode_response, client_name="pytest"
85+
)
8486
assert client
8587
assert client.redis_dsn == redis_resources_dns
88+
assert client.client_name == "pytest"
8689
await client.setup()
8790

8891
yield client
@@ -94,7 +97,9 @@ async def _cleanup_redis_data(clients_manager: RedisClientsManager) -> None:
9497
await clients_manager.client(db).redis.flushall()
9598

9699
async with RedisClientsManager(
97-
{RedisManagerDBConfig(db) for db in RedisDatabase}, redis_service
100+
{RedisManagerDBConfig(db) for db in RedisDatabase},
101+
redis_service,
102+
client_name="pytest",
98103
) as clients_manager:
99104
await _cleanup_redis_data(clients_manager)
100105
yield _

packages/service-library/tests/deferred_tasks/example_app.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ def __init__(self, redis_settings: RedisSettings, port: int) -> None:
6060
self.redis: Redis = RedisClientSDK(
6161
redis_settings.build_redis_dsn(RedisDatabase.DEFERRED_TASKS),
6262
decode_responses=True,
63+
client_name="example_app",
6364
).redis
6465
self.port = port
6566

@@ -84,6 +85,7 @@ def __init__(
8485
self._redis_client = RedisClientSDK(
8586
redis_settings.build_redis_dsn(RedisDatabase.DEFERRED_TASKS),
8687
decode_responses=False,
88+
client_name="example_app",
8789
)
8890
self._manager = DeferredManager(
8991
rabbit_settings,

packages/service-library/tests/deferred_tasks/test__base_deferred_handler.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ async def redis_client_sdk(
5555
sdk = RedisClientSDK(
5656
redis_service.build_redis_dsn(RedisDatabase.DEFERRED_TASKS),
5757
decode_responses=False,
58+
client_name="pytest",
5859
)
5960
await sdk.setup()
6061
yield sdk

packages/service-library/tests/test_pools.py

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from asyncio import BaseEventLoop
1+
import asyncio
22
from concurrent.futures import ProcessPoolExecutor
33

44
from servicelib.pools import (
@@ -11,17 +11,25 @@ def return_int_one() -> int:
1111
return 1
1212

1313

14-
async def test_default_thread_pool_executor(event_loop: BaseEventLoop) -> None:
15-
assert await event_loop.run_in_executor(None, return_int_one) == 1
14+
async def test_default_thread_pool_executor() -> None:
15+
assert await asyncio.get_running_loop().run_in_executor(None, return_int_one) == 1
1616

1717

18-
async def test_blocking_process_pool_executor(event_loop: BaseEventLoop) -> None:
19-
assert await event_loop.run_in_executor(ProcessPoolExecutor(), return_int_one) == 1
18+
async def test_blocking_process_pool_executor() -> None:
19+
assert (
20+
await asyncio.get_running_loop().run_in_executor(
21+
ProcessPoolExecutor(), return_int_one
22+
)
23+
== 1
24+
)
2025

2126

22-
async def test_non_blocking_process_pool_executor(event_loop: BaseEventLoop) -> None:
27+
async def test_non_blocking_process_pool_executor() -> None:
2328
with non_blocking_process_pool_executor() as executor:
24-
assert await event_loop.run_in_executor(executor, return_int_one) == 1
29+
assert (
30+
await asyncio.get_running_loop().run_in_executor(executor, return_int_one)
31+
== 1
32+
)
2533

2634

2735
async def test_same_pool_instances() -> None:
@@ -36,9 +44,12 @@ async def test_different_pool_instances() -> None:
3644
assert first != second
3745

3846

39-
async def test_non_blocking_thread_pool_executor(event_loop: BaseEventLoop) -> None:
47+
async def test_non_blocking_thread_pool_executor() -> None:
4048
with non_blocking_thread_pool_executor() as executor:
41-
assert await event_loop.run_in_executor(executor, return_int_one) == 1
49+
assert (
50+
await asyncio.get_running_loop().run_in_executor(executor, return_int_one)
51+
== 1
52+
)
4253

4354

4455
async def test_same_thread_pool_instances() -> None:

packages/service-library/tests/test_redis.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,9 @@ async def test_redis_client_sdks_manager(
277277
RedisManagerDBConfig(db) for db in RedisDatabase
278278
}
279279
manager = RedisClientsManager(
280-
databases_configs=all_redis_configs, settings=redis_service
280+
databases_configs=all_redis_configs,
281+
settings=redis_service,
282+
client_name="pytest",
281283
)
282284

283285
async with manager:
@@ -290,7 +292,7 @@ async def test_redis_client_sdk_setup_shutdown(
290292
):
291293
# setup
292294
redis_resources_dns = redis_service.build_redis_dsn(RedisDatabase.RESOURCES)
293-
client = RedisClientSDK(redis_resources_dns)
295+
client = RedisClientSDK(redis_resources_dns, client_name="pytest")
294296
assert client
295297
assert client.redis_dsn == redis_resources_dns
296298

0 commit comments

Comments
 (0)