Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
dc77030
intro
matusdrobuliak66 Apr 16, 2025
d47f6a6
revert
matusdrobuliak66 Apr 16, 2025
756b22a
fix test in director-v2
matusdrobuliak66 Apr 16, 2025
8b51296
fix
matusdrobuliak66 Apr 16, 2025
b13813c
fix
matusdrobuliak66 Apr 16, 2025
d7ece07
adding tests:
matusdrobuliak66 Apr 16, 2025
f82840e
Merge branch 'master' into add-listing-of-comp-runs
matusdrobuliak66 Apr 17, 2025
5eea03a
adding tests
matusdrobuliak66 Apr 17, 2025
840462a
adding tests to webserver
matusdrobuliak66 Apr 17, 2025
b2dc367
Merge branch 'master' into add-listing-of-comp-runs
matusdrobuliak66 Apr 17, 2025
b739492
remove comment
matusdrobuliak66 Apr 17, 2025
ee472d8
small cleanup
matusdrobuliak66 Apr 17, 2025
72f289e
add db indexes
matusdrobuliak66 Apr 17, 2025
243c5dc
fix
matusdrobuliak66 Apr 17, 2025
fb2a8d1
update open api specs
matusdrobuliak66 Apr 17, 2025
d786c64
review @pcrespov
matusdrobuliak66 Apr 17, 2025
f552f42
fix
matusdrobuliak66 Apr 17, 2025
93bb5ef
Merge branch 'master' into add-listing-of-comp-runs
matusdrobuliak66 Apr 22, 2025
cddeda5
Merge branch 'master' into add-listing-of-comp-runs
matusdrobuliak66 Apr 22, 2025
9e58ce3
review @sanderegg
matusdrobuliak66 Apr 22, 2025
d9ce804
Merge branch 'master' into add-listing-of-comp-runs
matusdrobuliak66 Apr 22, 2025
871f262
update open api specs
matusdrobuliak66 Apr 22, 2025
8db4e63
update open api specs
matusdrobuliak66 Apr 22, 2025
0ddce71
Merge branch 'master' into add-listing-of-comp-runs
matusdrobuliak66 Apr 22, 2025
cfc7164
Merge branch 'master' into add-listing-of-comp-runs
matusdrobuliak66 Apr 22, 2025
9bc685a
fix ordering of tasks
sanderegg Apr 22, 2025
97b0f7e
Merge branch 'master' into add-listing-of-comp-runs
matusdrobuliak66 Apr 22, 2025
05789b5
Merge branch 'master' into add-listing-of-comp-runs
odeimaiz Apr 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions api/specs/web-server/_computations.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from typing import Annotated

from _common import as_query
from fastapi import APIRouter, Depends, status
from models_library.api_schemas_webserver.computations import (
ComputationGet,
Expand All @@ -9,6 +10,11 @@
)
from models_library.generics import Envelope
from simcore_service_webserver._meta import API_VTAG
from simcore_service_webserver.director_v2._computations_rest_schema import (
ComputationRunListQueryParams,
ComputationTaskListQueryParams,
ComputationTaskPathParams,
)

router = APIRouter(
prefix=f"/{API_VTAG}",
Expand Down Expand Up @@ -53,3 +59,26 @@ async def start_computation(
status_code=status.HTTP_204_NO_CONTENT,
)
async def stop_computation(_path: Annotated[ComputationPathParams, Depends()]): ...


@router.get(
"/computations/-/iterations/latest",
response_model=Envelope[list[ComputationGet]],
name="list_computations_latest_iteration",
description="Lists the latest iteration of computations",
)
async def list_computations_latest_iteration(
_query: Annotated[as_query(ComputationRunListQueryParams), Depends()],
): ...


@router.get(
"/computations/{project_id}/iterations/latest/tasks",
response_model=Envelope[list[ComputationGet]],
name="list_computations_latest_iteration_tasks",
description="Lists the latest iteration tasks for a computation",
)
async def list_computations_latest_iteration_tasks(
_query: Annotated[as_query(ComputationTaskListQueryParams), Depends()],
_path: Annotated[ComputationTaskPathParams, Depends()],
): ...
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
from typing import Final

from pydantic import TypeAdapter

from ..rabbitmq_basic_types import RPCNamespace
from . import clusters, dynamic_services

assert clusters # nosec
assert dynamic_services # nosec


DIRECTOR_V2_RPC_NAMESPACE: Final[RPCNamespace] = TypeAdapter(
RPCNamespace
).validate_python("director-v2")


__all__: tuple[str, ...] = (
"clusters",
"dynamic_services",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
from datetime import datetime
from typing import Annotated, Any, NamedTuple

from pydantic import (
BaseModel,
BeforeValidator,
ConfigDict,
PositiveInt,
)

from ..projects import ProjectID
from ..projects_nodes_io import NodeID
from ..projects_state import RunningState


class ComputationRunRpcGet(BaseModel):
project_uuid: ProjectID
iteration: int
state: RunningState
info: dict[str, Any]
submitted_at: datetime
started_at: datetime | None
ended_at: datetime | None

model_config = ConfigDict(
json_schema_extra={
"examples": [
{
"project_uuid": "beb16d18-d57d-44aa-a638-9727fa4a72ef",
"iteration": 1,
"state": "SUCCESS",
"info": {
"wallet_id": 9866,
"user_email": "[email protected]",
"wallet_name": "test",
"product_name": "osparc",
"project_name": "test",
"project_metadata": {
"parent_node_id": "12e0c8b2-bad6-40fb-9948-8dec4f65d4d9",
"parent_node_name": "UJyfwFVYySnPCaLuQIaz",
"parent_project_id": "beb16d18-d57d-44aa-a638-9727fa4a72ef",
"parent_project_name": "qTjDmYPxeqAWfCKCQCYF",
"root_parent_node_id": "37176e84-d977-4993-bc49-d76fcfc6e625",
"root_parent_node_name": "UEXExIZVPeFzGRmMglPr",
"root_parent_project_id": "beb16d18-d57d-44aa-a638-9727fa4a72ef",
"root_parent_project_name": "FuDpjjFIyeNTWRUWCuKo",
},
"node_id_names_map": {},
"simcore_user_agent": "agent",
},
"submitted_at": "2023-01-11 13:11:47.293595",
"started_at": "2023-01-11 13:11:47.293595",
"ended_at": "2023-01-11 13:11:47.293595",
}
]
}
)


class ComputationRunRpcGetPage(NamedTuple):
items: list[ComputationRunRpcGet]
total: PositiveInt


def _none_to_zero_float_pre_validator(value: Any):
if value is None:
return 0.0
return value


class ComputationTaskRpcGet(BaseModel):
project_uuid: ProjectID
node_id: NodeID
state: RunningState
progress: Annotated[float, BeforeValidator(_none_to_zero_float_pre_validator)]
image: dict[str, Any]
started_at: datetime | None
ended_at: datetime | None

model_config = ConfigDict(
json_schema_extra={
"examples": [
{
"project_uuid": "beb16d18-d57d-44aa-a638-9727fa4a72ef",
"node_id": "12e0c8b2-bad6-40fb-9948-8dec4f65d4d9",
"state": "SUCCESS",
"progress": 0.0,
"image": {
"name": "simcore/services/comp/ti-solutions-optimizer",
"tag": "1.0.19",
"node_requirements": {"CPU": 8.0, "RAM": 25769803776},
},
"started_at": "2023-01-11 13:11:47.293595",
"ended_at": "2023-01-11 13:11:47.293595",
}
]
}
)


class ComputationTaskRpcGetPage(NamedTuple):
items: list[ComputationTaskRpcGet]
total: PositiveInt
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
from typing import Annotated
from datetime import datetime
from typing import Annotated, Any, NamedTuple

from common_library.basic_types import DEFAULT_FACTORY
from pydantic import BaseModel, Field
from pydantic import (
BaseModel,
Field,
PositiveInt,
)

from ..api_schemas_directorv2.computations import (
ComputationGet as _DirectorV2ComputationGet,
)
from ..projects import CommitID, ProjectID
from ..projects_nodes_io import NodeID
from ..projects_state import RunningState
from ._base import InputSchemaWithoutCamelCase, OutputSchemaWithoutCamelCase


Expand Down Expand Up @@ -41,3 +48,33 @@ class ComputationStarted(OutputSchemaWithoutCamelCase):
json_schema_extra={"default": []},
),
] = DEFAULT_FACTORY


class ComputationRunRestGet(BaseModel):
project_uuid: ProjectID
iteration: int
state: RunningState
info: dict[str, Any]
submitted_at: datetime
started_at: datetime | None
ended_at: datetime | None


class ComputationRunRestGetPage(NamedTuple):
items: list[ComputationRunRestGet]
total: PositiveInt


class ComputationTaskRestGet(BaseModel):
project_uuid: ProjectID
node_id: NodeID
state: RunningState
progress: float
image: dict[str, Any]
started_at: datetime | None
ended_at: datetime | None


class ComputationTaskRestGetPage(NamedTuple):
items: list[ComputationTaskRestGet]
total: PositiveInt
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
"""add indexes to comp tables

Revision ID: f65f7786cd4b
Revises: cf8f743fd0b7
Create Date: 2025-04-17 12:44:27.577984+00:00

"""

import sqlalchemy as sa
from alembic import op

# revision identifiers, used by Alembic.
revision = "f65f7786cd4b"
down_revision = "cf8f743fd0b7"
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_index("ix_comp_runs_user_id", "comp_runs", ["user_id"], unique=False)
op.create_index(
"ix_comp_tasks_project_id", "comp_tasks", ["project_id"], unique=False
)
op.drop_index("idx_projects_last_change_date_desc", table_name="projects")
op.create_index(
"idx_projects_last_change_date_desc",
"projects",
["last_change_date"],
unique=False,
postgresql_using="btree",
postgresql_ops={"last_change_date": "DESC"},
)
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_index(
"idx_projects_last_change_date_desc",
table_name="projects",
postgresql_using="btree",
postgresql_ops={"last_change_date": "DESC"},
)
op.create_index(
"idx_projects_last_change_date_desc",
"projects",
[sa.text("last_change_date DESC")],
unique=False,
)
op.drop_index("ix_comp_tasks_project_id", table_name="comp_tasks")
op.drop_index("ix_comp_runs_user_id", table_name="comp_runs")
# ### end Alembic commands ###
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,5 @@
doc="the run uses on demand clusters",
),
sa.UniqueConstraint("project_uuid", "user_id", "iteration"),
sa.Index("ix_comp_runs_user_id", "user_id"),
)
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ class NodeClass(enum.Enum):
),
# ------
sa.UniqueConstraint("project_id", "node_id", name="project_node_uniqueness"),
sa.Index("ix_comp_tasks_project_id", "project_id"),
)

register_modified_datetime_auto_update_trigger(comp_tasks)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# pylint: disable=too-many-arguments
import logging
from typing import Final

from models_library.api_schemas_directorv2 import (
DIRECTOR_V2_RPC_NAMESPACE,
)
from models_library.api_schemas_directorv2.comp_runs import (
ComputationRunRpcGetPage,
ComputationTaskRpcGetPage,
)
from models_library.products import ProductName
from models_library.projects import ProjectID
from models_library.rabbitmq_basic_types import RPCMethodName
from models_library.rest_ordering import OrderBy
from models_library.users import UserID
from pydantic import NonNegativeInt, TypeAdapter

from ....logging_utils import log_decorator
from ... import RabbitMQRPCClient

_logger = logging.getLogger(__name__)


_DEFAULT_TIMEOUT_S: Final[NonNegativeInt] = 20

_RPC_METHOD_NAME_ADAPTER: TypeAdapter[RPCMethodName] = TypeAdapter(RPCMethodName)


@log_decorator(_logger, level=logging.DEBUG)
async def list_computations_latest_iteration_page(
rabbitmq_rpc_client: RabbitMQRPCClient,
*,
product_name: ProductName,
user_id: UserID,
# pagination
offset: int = 0,
limit: int = 20,
# ordering
order_by: OrderBy | None = None,
) -> ComputationRunRpcGetPage:
result = await rabbitmq_rpc_client.request(
DIRECTOR_V2_RPC_NAMESPACE,
_RPC_METHOD_NAME_ADAPTER.validate_python(
"list_computations_latest_iteration_page"
),
product_name=product_name,
user_id=user_id,
offset=offset,
limit=limit,
order_by=order_by,
timeout_s=_DEFAULT_TIMEOUT_S,
)
assert isinstance(result, ComputationRunRpcGetPage) # nosec
return result


@log_decorator(_logger, level=logging.DEBUG)
async def list_computations_latest_iteration_tasks_page(
rabbitmq_rpc_client: RabbitMQRPCClient,
*,
product_name: ProductName,
user_id: UserID,
project_id: ProjectID,
# pagination
offset: int = 0,
limit: int = 20,
# ordering
order_by: OrderBy | None = None,
) -> ComputationTaskRpcGetPage:
result = await rabbitmq_rpc_client.request(
DIRECTOR_V2_RPC_NAMESPACE,
_RPC_METHOD_NAME_ADAPTER.validate_python(
"list_computations_latest_iteration_tasks_page"
),
product_name=product_name,
user_id=user_id,
project_id=project_id,
offset=offset,
limit=limit,
order_by=order_by,
timeout_s=_DEFAULT_TIMEOUT_S,
)
assert isinstance(result, ComputationTaskRpcGetPage) # nosec
return result
Loading
Loading