Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
7354c1e
add skeleton endpoint for solver jobs
bisgaard-itis Aug 8, 2025
a719805
add 'hidden' to project patch model
bisgaard-itis Aug 11, 2025
7eeb160
add method for deleting jobs assets to JobService
bisgaard-itis Aug 11, 2025
1dece17
fix job_service method
bisgaard-itis Aug 11, 2025
7ad678a
first attempt at introducing 'get' method for project_marked_as_job
bisgaard-itis Aug 11, 2025
d3e09bf
add client method
bisgaard-itis Aug 11, 2025
d017714
add tests for get_project_marked_as_job method
bisgaard-itis Aug 11, 2025
a3f4692
explicit is better than implicit
bisgaard-itis Aug 11, 2025
a56062b
first attempt to do migration
bisgaard-itis Aug 11, 2025
28588af
update migration script
bisgaard-itis Aug 12, 2025
10ed5ba
modify tests and repo-service layers to acommodate storage_data_deleted
bisgaard-itis Aug 12, 2025
703bdf5
add test for storage_data_deletted
bisgaard-itis Aug 12, 2025
d25638b
fix tests
bisgaard-itis Aug 12, 2025
daf9445
ensure storage_data_deleted_column can be updated
bisgaard-itis Aug 12, 2025
25364f7
minor changes in api-server
bisgaard-itis Aug 12, 2025
175ff33
Merge branch '219-delete-job-s3-data' into 219-webserver-part-for-del…
bisgaard-itis Aug 12, 2025
562ebff
polish endspoint exposed in api-server
bisgaard-itis Aug 12, 2025
6cecc0f
only require project_uuid to get project_marked as job
bisgaard-itis Aug 12, 2025
07c7fbc
create domain model for jobs
bisgaard-itis Aug 12, 2025
ffce9cd
Revert "create domain model for jobs"
bisgaard-itis Aug 13, 2025
0425414
Revert "only require project_uuid to get project_marked as job"
bisgaard-itis Aug 13, 2025
9a01f15
add method for getting job which also checks parent resource
bisgaard-itis Aug 13, 2025
68156b5
minor fix
bisgaard-itis Aug 13, 2025
1cde55b
Merge branch 'master' into 219-webserver-part-for-deleting-job-data
bisgaard-itis Aug 13, 2025
88bbe32
minor bugfix
bisgaard-itis Aug 13, 2025
b3165d1
add return type in WbApiRpcClient.get_project_marked_as_job
bisgaard-itis Aug 13, 2025
36fd97b
fix webserver rpc mocks
bisgaard-itis Aug 13, 2025
9bd8349
fix fixture in api-server unit tests
bisgaard-itis Aug 13, 2025
ee3ab9d
fix pylint tests
bisgaard-itis Aug 13, 2025
dbe3c0a
add tests for get_project_marked_as_job
bisgaard-itis Aug 13, 2025
af2a969
add unit tests for get_job_method
bisgaard-itis Aug 13, 2025
34e7622
first attempt at adding unittest for entire api-server endpoint
bisgaard-itis Aug 13, 2025
88be256
improve unittest of delete assets endpoint
bisgaard-itis Aug 13, 2025
23da7db
Merge branch 'master' into 219-webserver-part-for-deleting-job-data
bisgaard-itis Aug 13, 2025
6a09516
refuse to start solver job whose assets are missing
bisgaard-itis Aug 13, 2025
987186a
Merge branch 'master' into 219-webserver-part-for-deleting-job-data
bisgaard-itis Aug 13, 2025
da5e80e
update openapi specs
bisgaard-itis Aug 13, 2025
58cdb7e
minor fix
bisgaard-itis Aug 13, 2025
0258422
raise instead of returning
bisgaard-itis Aug 13, 2025
b357b0a
fix tests
bisgaard-itis Aug 14, 2025
30e8046
fix all tests in test_api_solver_jobs.py
bisgaard-itis Aug 14, 2025
77ceacb
add test for checking new status code when starting job
bisgaard-itis Aug 14, 2025
f60d19b
cosmetic improvement
bisgaard-itis Aug 14, 2025
d1eca27
cleanup unused fixture
bisgaard-itis Aug 14, 2025
6577ac7
cosmetic fix
bisgaard-itis Aug 14, 2025
d8c3375
@GitHK dont mis bool and None
bisgaard-itis Aug 14, 2025
6e10f40
update openapi specs
bisgaard-itis Aug 14, 2025
749b33f
change published version in new endpoint
bisgaard-itis Aug 14, 2025
5e7d878
services/api-server version: 0.11.0 → 0.12.0
bisgaard-itis Aug 14, 2025
92b8f6b
update openapi specs
bisgaard-itis Aug 14, 2025
54d3a55
Merge branch 'master' into 219-webserver-part-for-deleting-job-data
bisgaard-itis Aug 14, 2025
e455fa0
Merge branch 'master' into 219-webserver-part-for-deleting-job-data
bisgaard-itis Aug 15, 2025
2edeae9
add check that assets are available when getting job outputs
bisgaard-itis Aug 15, 2025
4d5ba93
add test that 409 is returned when no assets available
bisgaard-itis Aug 15, 2025
9eb4da5
make patch input schema nullable
bisgaard-itis Aug 15, 2025
10db20e
update openapi specs
bisgaard-itis Aug 15, 2025
d005fa4
storage_data_deleted -> storage_assets_deleted
bisgaard-itis Aug 15, 2025
9ec50f5
use consistent naming
bisgaard-itis Aug 15, 2025
ae8940c
@sanderegg int -> UserID
bisgaard-itis Aug 15, 2025
c6d6681
fixes
bisgaard-itis Aug 15, 2025
0216e59
Merge branch 'master' into 219-webserver-part-for-deleting-job-data
bisgaard-itis Aug 15, 2025
4fed7f3
Merge branch 'master' into 219-webserver-part-for-deleting-job-data
bisgaard-itis Aug 15, 2025
bf41cfb
storage_data_deleted -> storage_assets_deleted
bisgaard-itis Aug 15, 2025
005c2d5
Merge branch 'master' into 219-webserver-part-for-deleting-job-data
bisgaard-itis Aug 15, 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
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ class ProjectPatch(InputSchema):
] = None
quality: dict[str, Any] | None = None
template_type: ProjectTemplateType | None = None
hidden: bool | None = None

def to_domain_model(self) -> dict[str, Any]:
return self.model_dump(exclude_unset=True, by_alias=False)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ class ProjectJobRpcGet(BaseModel):

# Specific to jobs
job_parent_resource_name: str
storage_assets_deleted: bool

@staticmethod
def _update_json_schema_extra(schema: JsonDict) -> None:
Expand All @@ -105,6 +106,7 @@ def _update_json_schema_extra(schema: JsonDict) -> None:
"created_at": "2023-01-01T00:00:00Z",
"modified_at": "2023-01-01T00:00:00Z",
"job_parent_resource_name": "solvers/simcore%2Fservices%2Fcomp%2Fitis%2Fsleeper/releases/2.0.2",
"storage_assets_deleted": "false",
},
{
"uuid": "00000000-1234-5678-1234-123456789012",
Expand All @@ -114,6 +116,7 @@ def _update_json_schema_extra(schema: JsonDict) -> None:
"created_at": "2023-02-01T00:00:00Z",
"modified_at": "2023-02-01T00:00:00Z",
"job_parent_resource_name": "studies/96642f2a-a72c-11ef-8776-02420a00087d",
"storage_assets_deleted": "true",
},
{
"uuid": "00000000-0000-5678-1234-123456789012",
Expand All @@ -123,6 +126,7 @@ def _update_json_schema_extra(schema: JsonDict) -> None:
"created_at": "2023-03-01T00:00:00Z",
"modified_at": "2023-03-01T00:00:00Z",
"job_parent_resource_name": "program/simcore%2Fservices%2Fdynamic%2Fjupyter/releases/5.0.2",
"storage_assets_deleted": "false",
},
]
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""introduce data_deleted in projects_to_jobs table

Revision ID: 5b998370916a
Revises: 5679165336c8
Create Date: 2025-08-11 13:58:38.424398+00:00

"""

import sqlalchemy as sa
from alembic import op

# revision identifiers, used by Alembic.
revision = "5b998370916a"
down_revision = "5679165336c8"
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column(
"projects_to_jobs",
sa.Column("storage_assets_deleted", sa.Boolean(), nullable=True),
)

op.execute("UPDATE projects_to_jobs SET storage_assets_deleted = false")

op.alter_column(
"projects_to_jobs",
"storage_assets_deleted",
existing_type=sa.BOOLEAN(),
nullable=False,
)
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("projects_to_jobs", "storage_assets_deleted")
# ### end Alembic commands ###
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@
"the relative resource name is shelves/shelf1/jobs/job2, "
"the parent resource name is shelves/shelf1.",
),
sa.Column(
"storage_assets_deleted",
sa.Boolean,
nullable=False,
doc="Indicates whether the job's S3 assets have been actively deleted.",
),
# Composite key (project_uuid, job_parent_resource_name) uniquely identifies very row
sa.UniqueConstraint(
"project_uuid",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@
class WebserverRpcSideEffects:
# pylint: disable=no-self-use

def __init__(
self,
project_job_rpc_get: ProjectJobRpcGet = ProjectJobRpcGet.model_validate(
ProjectJobRpcGet.model_json_schema()["examples"][0]
),
):
self.project_job_rpc_get = project_job_rpc_get

@validate_call(config={"arbitrary_types_allowed": True})
async def mark_project_as_job(
self,
Expand All @@ -35,12 +43,14 @@ async def mark_project_as_job(
user_id: UserID,
project_uuid: ProjectID,
job_parent_resource_name: str,
storage_assets_deleted: bool,
) -> None:
assert rpc_client

assert not job_parent_resource_name.startswith("/") # nosec
assert "/" in job_parent_resource_name # nosec
assert not job_parent_resource_name.endswith("/") # nosec
assert isinstance(storage_assets_deleted, bool)

assert product_name
assert user_id
Expand Down Expand Up @@ -84,3 +94,25 @@ async def list_projects_marked_as_jobs(
limit=limit,
offset=offset,
)

@validate_call(config={"arbitrary_types_allowed": True})
async def get_project_marked_as_job(
self,
rpc_client: RabbitMQRPCClient | MockType,
*,
product_name: ProductName,
user_id: UserID,
project_uuid: ProjectID,
job_parent_resource_name: str,
) -> ProjectJobRpcGet:
assert rpc_client
assert product_name
assert user_id
assert project_uuid
assert job_parent_resource_name

# Return a valid example from the schema
_data = self.project_job_rpc_get.model_dump()
_data["uuid"] = str(project_uuid)
_data["job_parent_resource_name"] = job_parent_resource_name
return ProjectJobRpcGet.model_validate(_data)
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from models_library.rpc.webserver.projects import (
ListProjectsMarkedAsJobRpcFilters,
PageRpcProjectJobRpcGet,
ProjectJobRpcGet,
)
from models_library.rpc_pagination import (
DEFAULT_NUMBER_OF_ITEMS_PER_PAGE,
Expand All @@ -32,6 +33,7 @@ async def mark_project_as_job(
user_id: UserID,
project_uuid: ProjectID,
job_parent_resource_name: str,
storage_assets_deleted: bool,
) -> None:

result = await rpc_client.request(
Expand All @@ -41,6 +43,7 @@ async def mark_project_as_job(
user_id=user_id,
project_uuid=project_uuid,
job_parent_resource_name=job_parent_resource_name,
storage_assets_deleted=storage_assets_deleted,
)
assert result is None

Expand Down Expand Up @@ -68,3 +71,25 @@ async def list_projects_marked_as_jobs(
)
assert TypeAdapter(PageRpcProjectJobRpcGet).validate_python(result) # nosec
return cast(PageRpcProjectJobRpcGet, result)


@log_decorator(_logger, level=logging.DEBUG)
@validate_call(config={"arbitrary_types_allowed": True})
async def get_project_marked_as_job(
rpc_client: RabbitMQRPCClient,
*,
product_name: ProductName,
user_id: UserID,
project_uuid: ProjectID,
job_parent_resource_name: str,
) -> ProjectJobRpcGet:
result = await rpc_client.request(
WEBSERVER_RPC_NAMESPACE,
TypeAdapter(RPCMethodName).validate_python("get_project_marked_as_job"),
product_name=product_name,
user_id=user_id,
project_uuid=project_uuid,
job_parent_resource_name=job_parent_resource_name,
)
assert TypeAdapter(ProjectJobRpcGet).validate_python(result) # nosec
return cast(ProjectJobRpcGet, result)
2 changes: 1 addition & 1 deletion services/api-server/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.11.0
0.12.0
154 changes: 153 additions & 1 deletion services/api-server/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"info": {
"title": "osparc.io public API",
"description": "osparc-simcore public API specifications",
"version": "0.11.0"
"version": "0.12.0"
},
"paths": {
"/v0/meta": {
Expand Down Expand Up @@ -2761,6 +2761,138 @@
}
}
},
"/v0/solvers/{solver_key}/releases/{version}/jobs/{job_id}/assets": {
"delete": {
"tags": [
"solvers"
],
"summary": "Delete Job Assets",
"description": "Deletes assets associated with an existing solver job. N.B. this renders the solver job un-startable\n\nNew in *version 0.12*",
"operationId": "delete_job_assets",
"security": [
{
"HTTPBasic": []
}
],
"parameters": [
{
"name": "solver_key",
"in": "path",
"required": true,
"schema": {
"type": "string",
"pattern": "^simcore/services/comp/([a-z0-9][a-z0-9_.-]*/)*([a-z0-9-_]+[a-z0-9])$",
"title": "Solver Key"
}
},
{
"name": "version",
"in": "path",
"required": true,
"schema": {
"type": "string",
"pattern": "^(0|[1-9]\\d*)(\\.(0|[1-9]\\d*)){2}(-(0|[1-9]\\d*|\\d*[-a-zA-Z][-\\da-zA-Z]*)(\\.(0|[1-9]\\d*|\\d*[-a-zA-Z][-\\da-zA-Z]*))*)?(\\+[-\\da-zA-Z]+(\\.[-\\da-zA-Z-]+)*)?$",
"title": "Version"
}
},
{
"name": "job_id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid",
"title": "Job Id"
}
}
],
"responses": {
"204": {
"description": "Successful Response"
},
"402": {
"description": "Payment required",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorGet"
}
}
}
},
"404": {
"description": "Job/wallet/pricing details not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorGet"
}
}
}
},
"429": {
"description": "Too many requests",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorGet"
}
}
}
},
"500": {
"description": "Internal server error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorGet"
}
}
}
},
"502": {
"description": "Unexpected error when communicating with backend service",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorGet"
}
}
}
},
"503": {
"description": "Service unavailable",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorGet"
}
}
}
},
"504": {
"description": "Request to a backend service timed out.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorGet"
}
}
}
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
}
}
}
}
},
"/v0/solvers/{solver_key}/releases/{version}/jobs/{job_id}:start": {
"post": {
"tags": [
Expand Down Expand Up @@ -2926,6 +3058,16 @@
}
}
},
"409": {
"description": "Job assets missing",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorGet"
}
}
}
},
"422": {
"description": "Configuration error",
"content": {
Expand Down Expand Up @@ -3760,6 +3902,16 @@
}
}
},
"409": {
"description": "Job assets missing",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorGet"
}
}
}
},
"422": {
"description": "Validation Error",
"content": {
Expand Down
2 changes: 1 addition & 1 deletion services/api-server/setup.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.11.0
current_version = 0.12.0
commit = True
message = services/api-server version: {current_version} → {new_version}
tag = False
Expand Down
Loading
Loading