Skip to content

Commit d53ef0d

Browse files
authored
Merge branch 'master' into hotfix-get-computation-run-remove-user-id
2 parents 910843c + b901a65 commit d53ef0d

File tree

59 files changed

+731
-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.

59 files changed

+731
-406
lines changed

api/specs/web-server/_auth.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from models_library.rest_error import EnvelopedError, Log
1616
from pydantic import BaseModel, Field, confloat
1717
from simcore_service_webserver._meta import API_VTAG
18-
from simcore_service_webserver.login._controller.rest.auth import (
18+
from simcore_service_webserver.login._controller.rest.auth_schemas import (
1919
LoginBody,
2020
LoginNextPage,
2121
LoginTwoFactorAuthBody,
@@ -30,7 +30,7 @@
3030
PhoneConfirmationBody,
3131
ResetPasswordConfirmation,
3232
)
33-
from simcore_service_webserver.login._controller.rest.registration import (
33+
from simcore_service_webserver.login._controller.rest.registration_schemas import (
3434
InvitationCheck,
3535
InvitationInfo,
3636
RegisterBody,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"""computational collection uniquencess
2+
3+
Revision ID: 61b98a60e934
4+
Revises: df61d1b2b967
5+
Create Date: 2025-07-08 15:40:12.714684+00:00
6+
7+
"""
8+
9+
from alembic import op
10+
11+
# revision identifiers, used by Alembic.
12+
revision = "61b98a60e934"
13+
down_revision = "df61d1b2b967"
14+
branch_labels = None
15+
depends_on = None
16+
17+
18+
def upgrade():
19+
# ### commands auto generated by Alembic - please adjust! ###
20+
op.create_unique_constraint(
21+
"client_or_system_generated_id_uniqueness",
22+
"comp_runs_collections",
23+
["client_or_system_generated_id"],
24+
)
25+
# ### end Alembic commands ###
26+
27+
28+
def downgrade():
29+
# ### commands auto generated by Alembic - please adjust! ###
30+
op.drop_constraint(
31+
"client_or_system_generated_id_uniqueness",
32+
"comp_runs_collections",
33+
type_="unique",
34+
)
35+
# ### end Alembic commands ###

packages/postgres-database/src/simcore_postgres_database/models/comp_runs_collections.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,7 @@
3535
"ix_comp_runs_collections_client_or_system_generated_id",
3636
"client_or_system_generated_id",
3737
),
38+
sa.UniqueConstraint(
39+
"client_or_system_generated_id", name="client_or_system_generated_id_uniqueness"
40+
),
3841
)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55

66
from aiohttp.test_utils import TestClient
77
from servicelib.aiohttp import status
8-
from simcore_service_webserver.login._constants import MSG_LOGGED_IN
98
from simcore_service_webserver.login._invitations_service import create_invitation_token
109
from simcore_service_webserver.login._login_repository_legacy import (
1110
get_plugin_storage,
1211
)
12+
from simcore_service_webserver.login.constants import MSG_LOGGED_IN
1313
from simcore_service_webserver.security import security_service
1414
from yarl import URL
1515

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

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
)
2626
from .typing_extension import Handler
2727

28-
log = logging.getLogger(__name__)
28+
_logger = logging.getLogger(__name__)
2929

3030
_PROMETHEUS_METRICS: Final[str] = f"{__name__}.prometheus_metrics" # noqa: N816
3131

@@ -59,7 +59,6 @@ def middleware_factory(
5959
async def middleware_handler(request: web.Request, handler: Handler):
6060
# See https://prometheus.io/docs/concepts/metric_types
6161

62-
log_exception: BaseException | None = None
6362
response: web.StreamResponse = web.HTTPInternalServerError()
6463

6564
canonical_endpoint = request.path
@@ -68,7 +67,7 @@ async def middleware_handler(request: web.Request, handler: Handler):
6867
start_time = perf_counter()
6968
try:
7069
if enter_middleware_cb:
71-
with log_catch(logger=log, reraise=False):
70+
with log_catch(logger=_logger, reraise=False):
7271
await enter_middleware_cb(request)
7372

7473
metrics = request.app[_PROMETHEUS_METRICS]
@@ -92,16 +91,10 @@ async def middleware_handler(request: web.Request, handler: Handler):
9291

9392
except web.HTTPServerError as exc:
9493
response = exc
95-
log_exception = exc
9694
raise
9795

9896
except web.HTTPException as exc:
9997
response = exc
100-
log_exception = None
101-
raise
102-
103-
except Exception as exc: # pylint: disable=broad-except
104-
log_exception = exc
10598
raise
10699

107100
finally:
@@ -117,23 +110,9 @@ async def middleware_handler(request: web.Request, handler: Handler):
117110
)
118111

119112
if exit_middleware_cb:
120-
with log_catch(logger=log, reraise=False):
113+
with log_catch(logger=_logger, reraise=False):
121114
await exit_middleware_cb(request, response)
122115

123-
if log_exception:
124-
log.error(
125-
'Unexpected server error "%s" from access: %s "%s %s" done '
126-
"in %3.2f secs. Responding with status %s",
127-
type(log_exception),
128-
request.remote,
129-
request.method,
130-
request.path,
131-
response_latency_seconds,
132-
response.status,
133-
exc_info=log_exception,
134-
stack_info=True,
135-
)
136-
137116
return response
138117

139118
setattr( # noqa: B010

packages/service-library/src/servicelib/rabbitmq/rpc_interfaces/director_v2/computations.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ async def list_computation_collection_runs_page(
126126
product_name: ProductName,
127127
user_id: UserID,
128128
project_ids: list[ProjectID] | None,
129+
filter_only_running: bool = False,
129130
# pagination
130131
offset: int = 0,
131132
limit: int = 20,
@@ -138,6 +139,7 @@ async def list_computation_collection_runs_page(
138139
product_name=product_name,
139140
user_id=user_id,
140141
project_ids=project_ids,
142+
filter_only_running=filter_only_running,
141143
offset=offset,
142144
limit=limit,
143145
timeout_s=_DEFAULT_TIMEOUT_S,

services/director-v2/src/simcore_service_director_v2/api/rpc/_computations.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,15 +102,24 @@ async def list_computation_collection_runs_page(
102102
product_name: ProductName,
103103
user_id: UserID,
104104
project_ids: list[ProjectID] | None,
105+
filter_only_running: bool = False,
105106
# pagination
106107
offset: int = 0,
107108
limit: int = 20,
108109
) -> ComputationCollectionRunRpcGetPage:
109110
comp_runs_repo = CompRunsRepository.instance(db_engine=app.state.engine)
111+
112+
collection_run_ids: list[CollectionRunID] | None = None
113+
if filter_only_running is True:
114+
collection_run_ids = await comp_runs_repo.list_all_collection_run_ids_for_user_currently_running_computations(
115+
product_name=product_name, user_id=user_id
116+
)
117+
110118
total, comp_runs_output = await comp_runs_repo.list_group_by_collection_run_id(
111119
product_name=product_name,
112120
user_id=user_id,
113-
project_ids=project_ids,
121+
project_ids_or_none=project_ids,
122+
collection_run_ids_or_none=collection_run_ids,
114123
offset=offset,
115124
limit=limit,
116125
)

services/director-v2/src/simcore_service_director_v2/modules/db/repositories/comp_runs.py

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -393,12 +393,46 @@ async def list_for_user_and_project_all_iterations(
393393

394394
return cast(int, total_count), items
395395

396+
async def list_all_collection_run_ids_for_user_currently_running_computations(
397+
self,
398+
*,
399+
product_name: str,
400+
user_id: UserID,
401+
) -> list[CollectionRunID]:
402+
403+
list_query = (
404+
sa.select(
405+
comp_runs.c.collection_run_id,
406+
)
407+
.where(
408+
(comp_runs.c.user_id == user_id)
409+
& (
410+
comp_runs.c.metadata["product_name"].astext == product_name
411+
) # <-- NOTE: We might create a separate column for this for fast retrieval
412+
& (
413+
comp_runs.c.result.in_(
414+
[
415+
RUNNING_STATE_TO_DB[item]
416+
for item in RunningState.list_running_states()
417+
]
418+
)
419+
)
420+
)
421+
.distinct()
422+
)
423+
424+
async with pass_or_acquire_connection(self.db_engine) as conn:
425+
return [
426+
CollectionRunID(row[0]) async for row in await conn.stream(list_query)
427+
]
428+
396429
async def list_group_by_collection_run_id(
397430
self,
398431
*,
399432
product_name: str,
400433
user_id: UserID,
401-
project_ids: list[ProjectID] | None = None,
434+
project_ids_or_none: list[ProjectID] | None = None,
435+
collection_run_ids_or_none: list[CollectionRunID] | None = None,
402436
# pagination
403437
offset: int,
404438
limit: int,
@@ -424,10 +458,19 @@ async def list_group_by_collection_run_id(
424458
& (comp_runs.c.metadata["product_name"].astext == product_name)
425459
)
426460

427-
if project_ids:
461+
if project_ids_or_none:
428462
base_select_query = base_select_query.where(
429463
comp_runs.c.project_uuid.in_(
430-
[f"{project_id}" for project_id in project_ids]
464+
[f"{project_id}" for project_id in project_ids_or_none]
465+
)
466+
)
467+
if collection_run_ids_or_none:
468+
base_select_query = base_select_query.where(
469+
comp_runs.c.collection_run_id.in_(
470+
[
471+
f"{collection_run_id}"
472+
for collection_run_id in collection_run_ids_or_none
473+
]
431474
)
432475
)
433476

services/director-v2/tests/unit/with_dbs/comp_scheduler/test_api_rpc_computations.py

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -265,18 +265,29 @@ async def test_rpc_list_computation_collection_runs_page_and_collection_run_task
265265
not_default_collection_run_id,
266266
]
267267

268-
for proj, collection_run_id in zip(projects, collection_run_id_project_list):
268+
running_state_project_list = [
269+
RunningState.SUCCESS,
270+
RunningState.PENDING,
271+
RunningState.SUCCESS,
272+
]
273+
274+
for proj, collection_run_id, running_state in zip(
275+
projects,
276+
collection_run_id_project_list,
277+
running_state_project_list,
278+
strict=True,
279+
):
269280
await create_pipeline(
270281
project_id=f"{proj.uuid}",
271282
dag_adjacency_list=fake_workbench_adjacency,
272283
)
273284
await create_tasks_from_project(
274-
user=user, project=proj, state=StateType.PUBLISHED, progress=None
285+
user=user, project=proj, state=running_state, progress=None
275286
)
276287
run = await create_comp_run(
277288
user=user,
278289
project=proj,
279-
result=RunningState.SUCCESS,
290+
result=running_state,
280291
started=datetime.now(tz=UTC) - timedelta(minutes=120),
281292
ended=datetime.now(tz=UTC) - timedelta(minutes=100),
282293
iteration=1,
@@ -317,3 +328,16 @@ async def test_rpc_list_computation_collection_runs_page_and_collection_run_task
317328
assert output.total == 4
318329
assert len(output.items) == 4
319330
isinstance(output, ComputationCollectionRunTaskRpcGetPage)
331+
332+
# Test filtering only running collection runs
333+
output = await rpc_computations.list_computation_collection_runs_page(
334+
rpc_client,
335+
product_name="osparc",
336+
user_id=user["id"],
337+
project_ids=None,
338+
filter_only_running=True, # <-- This is the tested filter
339+
)
340+
assert output.total == 1
341+
assert len(output.items) == 1
342+
assert isinstance(output, ComputationCollectionRunRpcGetPage)
343+
assert len(output.items[0].project_ids) == 2

services/director-v2/tests/unit/with_dbs/comp_scheduler/test_db_repositories_comp_runs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1019,7 +1019,7 @@ async def test_list_group_by_collection_run_id_with_project_filter(
10191019
total_count, items = await repo.list_group_by_collection_run_id(
10201020
product_name=run_metadata.get("product_name"),
10211021
user_id=published_project_1.user["id"],
1022-
project_ids=[
1022+
project_ids_or_none=[
10231023
published_project_1.project.uuid,
10241024
published_project_2.project.uuid,
10251025
],

0 commit comments

Comments
 (0)