Skip to content

Commit 67f44e3

Browse files
author
Andrei Neagu
committed
Merge remote-tracking branch 'upstream/master' into pr-osparc-long-running-rabbitmq-client
2 parents 159ab96 + 8a62bd4 commit 67f44e3

File tree

54 files changed

+1342
-99
lines changed

Some content is hidden

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

54 files changed

+1342
-99
lines changed

.env-devel

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,8 @@ POSTGRES_HOST=postgres
195195
POSTGRES_PASSWORD=adminadmin
196196
POSTGRES_PORT=5432
197197
POSTGRES_USER=scu
198-
198+
POSTGRES_MINSIZE=2 # see https://github.com/ITISFoundation/osparc-simcore/pull/8199
199+
POSTGRES_MAXSIZE=50
199200
POSTGRES_READONLY_PASSWORD=readonly
200201
POSTGRES_READONLY_USER=postgres_readonly
201202

packages/models-library/src/models_library/api_schemas_webserver/projects.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ class ProjectPatch(InputSchema):
278278
] = None
279279
quality: dict[str, Any] | None = None
280280
template_type: ProjectTemplateType | None = None
281+
hidden: bool | None = None
281282

282283
def to_domain_model(self) -> dict[str, Any]:
283284
return self.model_dump(exclude_unset=True, by_alias=False)

packages/models-library/src/models_library/rpc/webserver/projects.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ class ProjectJobRpcGet(BaseModel):
9090

9191
# Specific to jobs
9292
job_parent_resource_name: str
93+
storage_assets_deleted: bool
9394

9495
@staticmethod
9596
def _update_json_schema_extra(schema: JsonDict) -> None:
@@ -105,6 +106,7 @@ def _update_json_schema_extra(schema: JsonDict) -> None:
105106
"created_at": "2023-01-01T00:00:00Z",
106107
"modified_at": "2023-01-01T00:00:00Z",
107108
"job_parent_resource_name": "solvers/simcore%2Fservices%2Fcomp%2Fitis%2Fsleeper/releases/2.0.2",
109+
"storage_assets_deleted": "false",
108110
},
109111
{
110112
"uuid": "00000000-1234-5678-1234-123456789012",
@@ -114,6 +116,7 @@ def _update_json_schema_extra(schema: JsonDict) -> None:
114116
"created_at": "2023-02-01T00:00:00Z",
115117
"modified_at": "2023-02-01T00:00:00Z",
116118
"job_parent_resource_name": "studies/96642f2a-a72c-11ef-8776-02420a00087d",
119+
"storage_assets_deleted": "true",
117120
},
118121
{
119122
"uuid": "00000000-0000-5678-1234-123456789012",
@@ -123,6 +126,7 @@ def _update_json_schema_extra(schema: JsonDict) -> None:
123126
"created_at": "2023-03-01T00:00:00Z",
124127
"modified_at": "2023-03-01T00:00:00Z",
125128
"job_parent_resource_name": "program/simcore%2Fservices%2Fdynamic%2Fjupyter/releases/5.0.2",
129+
"storage_assets_deleted": "false",
126130
},
127131
]
128132
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
"""introduce data_deleted in projects_to_jobs table
2+
3+
Revision ID: 5b998370916a
4+
Revises: 5679165336c8
5+
Create Date: 2025-08-11 13:58:38.424398+00:00
6+
7+
"""
8+
9+
import sqlalchemy as sa
10+
from alembic import op
11+
12+
# revision identifiers, used by Alembic.
13+
revision = "5b998370916a"
14+
down_revision = "5679165336c8"
15+
branch_labels = None
16+
depends_on = None
17+
18+
19+
def upgrade():
20+
# ### commands auto generated by Alembic - please adjust! ###
21+
op.add_column(
22+
"projects_to_jobs",
23+
sa.Column("storage_assets_deleted", sa.Boolean(), nullable=True),
24+
)
25+
26+
op.execute("UPDATE projects_to_jobs SET storage_assets_deleted = false")
27+
28+
op.alter_column(
29+
"projects_to_jobs",
30+
"storage_assets_deleted",
31+
existing_type=sa.BOOLEAN(),
32+
nullable=False,
33+
)
34+
# ### end Alembic commands ###
35+
36+
37+
def downgrade():
38+
# ### commands auto generated by Alembic - please adjust! ###
39+
op.drop_column("projects_to_jobs", "storage_assets_deleted")
40+
# ### end Alembic commands ###

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@
2828
"the relative resource name is shelves/shelf1/jobs/job2, "
2929
"the parent resource name is shelves/shelf1.",
3030
),
31+
sa.Column(
32+
"storage_assets_deleted",
33+
sa.Boolean,
34+
nullable=False,
35+
doc="Indicates whether the job's S3 assets have been actively deleted.",
36+
),
3137
# Composite key (project_uuid, job_parent_resource_name) uniquely identifies very row
3238
sa.UniqueConstraint(
3339
"project_uuid",

packages/postgres-database/tests/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def sync_engine(postgres_service: str) -> Iterable[sqlalchemy.engine.Engine]:
8181
def _make_asyncpg_engine(postgres_service: str) -> Callable[[bool], AsyncEngine]:
8282
# NOTE: users is responsible of `await engine.dispose()`
8383
dsn = postgres_service.replace("postgresql://", "postgresql+asyncpg://")
84-
minsize = 1
84+
minsize = 2
8585
maxsize = 50
8686

8787
def _(echo: bool):

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@
2626
class WebserverRpcSideEffects:
2727
# pylint: disable=no-self-use
2828

29+
def __init__(
30+
self,
31+
project_job_rpc_get: ProjectJobRpcGet = ProjectJobRpcGet.model_validate(
32+
ProjectJobRpcGet.model_json_schema()["examples"][0]
33+
),
34+
):
35+
self.project_job_rpc_get = project_job_rpc_get
36+
2937
@validate_call(config={"arbitrary_types_allowed": True})
3038
async def mark_project_as_job(
3139
self,
@@ -35,12 +43,14 @@ async def mark_project_as_job(
3543
user_id: UserID,
3644
project_uuid: ProjectID,
3745
job_parent_resource_name: str,
46+
storage_assets_deleted: bool,
3847
) -> None:
3948
assert rpc_client
4049

4150
assert not job_parent_resource_name.startswith("/") # nosec
4251
assert "/" in job_parent_resource_name # nosec
4352
assert not job_parent_resource_name.endswith("/") # nosec
53+
assert isinstance(storage_assets_deleted, bool)
4454

4555
assert product_name
4656
assert user_id
@@ -84,3 +94,25 @@ async def list_projects_marked_as_jobs(
8494
limit=limit,
8595
offset=offset,
8696
)
97+
98+
@validate_call(config={"arbitrary_types_allowed": True})
99+
async def get_project_marked_as_job(
100+
self,
101+
rpc_client: RabbitMQRPCClient | MockType,
102+
*,
103+
product_name: ProductName,
104+
user_id: UserID,
105+
project_uuid: ProjectID,
106+
job_parent_resource_name: str,
107+
) -> ProjectJobRpcGet:
108+
assert rpc_client
109+
assert product_name
110+
assert user_id
111+
assert project_uuid
112+
assert job_parent_resource_name
113+
114+
# Return a valid example from the schema
115+
_data = self.project_job_rpc_get.model_dump()
116+
_data["uuid"] = str(project_uuid)
117+
_data["job_parent_resource_name"] = job_parent_resource_name
118+
return ProjectJobRpcGet.model_validate(_data)

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,16 @@ async def create_async_engine_and_database_ready(
3030
raise_if_migration_not_ready,
3131
)
3232

33-
server_settings = None
33+
server_settings = {
34+
"jit": "off"
35+
} # see https://docs.sqlalchemy.org/en/20/dialects/postgresql.html#disabling-the-postgresql-jit-to-improve-enum-datatype-handling
3436
if settings.POSTGRES_CLIENT_NAME:
3537
assert isinstance(settings.POSTGRES_CLIENT_NAME, str) # nosec
36-
server_settings = {
37-
"application_name": settings.POSTGRES_CLIENT_NAME,
38-
}
38+
server_settings.update(
39+
{
40+
"application_name": settings.POSTGRES_CLIENT_NAME,
41+
}
42+
)
3943

4044
engine = create_async_engine(
4145
settings.dsn_with_async_sqlalchemy,

packages/service-library/src/servicelib/rabbitmq/rpc_interfaces/webserver/functions/functions_rpc_interface.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@
1717
RegisteredFunctionJobCollection,
1818
)
1919
from models_library.functions import (
20+
FunctionClass,
2021
FunctionJobStatus,
2122
FunctionOutputs,
2223
FunctionUserAccessRights,
2324
FunctionUserApiAccessRights,
2425
)
2526
from models_library.products import ProductName
2627
from models_library.rabbitmq_basic_types import RPCMethodName
28+
from models_library.rest_ordering import OrderBy
2729
from models_library.rest_pagination import PageMetaInfoLimitOffset
2830
from models_library.users import UserID
2931
from pydantic import TypeAdapter
@@ -135,6 +137,10 @@ async def list_functions(
135137
product_name: ProductName,
136138
pagination_offset: int,
137139
pagination_limit: int,
140+
order_by: OrderBy | None = None,
141+
filter_by_function_class: FunctionClass | None = None,
142+
search_by_function_title: str | None = None,
143+
search_by_multi_columns: str | None = None,
138144
) -> tuple[list[RegisteredFunction], PageMetaInfoLimitOffset]:
139145
result: tuple[list[RegisteredFunction], PageMetaInfoLimitOffset] = (
140146
await rabbitmq_rpc_client.request(
@@ -144,6 +150,10 @@ async def list_functions(
144150
pagination_limit=pagination_limit,
145151
user_id=user_id,
146152
product_name=product_name,
153+
order_by=order_by,
154+
filter_by_function_class=filter_by_function_class,
155+
search_by_function_title=search_by_function_title,
156+
search_by_multi_columns=search_by_multi_columns,
147157
)
148158
)
149159
return TypeAdapter(

packages/service-library/src/servicelib/rabbitmq/rpc_interfaces/webserver/projects.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from models_library.rpc.webserver.projects import (
1010
ListProjectsMarkedAsJobRpcFilters,
1111
PageRpcProjectJobRpcGet,
12+
ProjectJobRpcGet,
1213
)
1314
from models_library.rpc_pagination import (
1415
DEFAULT_NUMBER_OF_ITEMS_PER_PAGE,
@@ -32,6 +33,7 @@ async def mark_project_as_job(
3233
user_id: UserID,
3334
project_uuid: ProjectID,
3435
job_parent_resource_name: str,
36+
storage_assets_deleted: bool,
3537
) -> None:
3638

3739
result = await rpc_client.request(
@@ -41,6 +43,7 @@ async def mark_project_as_job(
4143
user_id=user_id,
4244
project_uuid=project_uuid,
4345
job_parent_resource_name=job_parent_resource_name,
46+
storage_assets_deleted=storage_assets_deleted,
4447
)
4548
assert result is None
4649

@@ -68,3 +71,25 @@ async def list_projects_marked_as_jobs(
6871
)
6972
assert TypeAdapter(PageRpcProjectJobRpcGet).validate_python(result) # nosec
7073
return cast(PageRpcProjectJobRpcGet, result)
74+
75+
76+
@log_decorator(_logger, level=logging.DEBUG)
77+
@validate_call(config={"arbitrary_types_allowed": True})
78+
async def get_project_marked_as_job(
79+
rpc_client: RabbitMQRPCClient,
80+
*,
81+
product_name: ProductName,
82+
user_id: UserID,
83+
project_uuid: ProjectID,
84+
job_parent_resource_name: str,
85+
) -> ProjectJobRpcGet:
86+
result = await rpc_client.request(
87+
WEBSERVER_RPC_NAMESPACE,
88+
TypeAdapter(RPCMethodName).validate_python("get_project_marked_as_job"),
89+
product_name=product_name,
90+
user_id=user_id,
91+
project_uuid=project_uuid,
92+
job_parent_resource_name=job_parent_resource_name,
93+
)
94+
assert TypeAdapter(ProjectJobRpcGet).validate_python(result) # nosec
95+
return cast(ProjectJobRpcGet, result)

0 commit comments

Comments
 (0)