Skip to content
Open
Show file tree
Hide file tree
Changes from 44 commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
988004b
batch cache endpoint
bisgaard-itis Oct 13, 2025
9924f3d
improve sql query
bisgaard-itis Oct 13, 2025
db49588
start using cache
bisgaard-itis Oct 13, 2025
4a954f6
implement cache in api-server
bisgaard-itis Oct 13, 2025
d3b9353
first attempt at batching function job creation
bisgaard-itis Oct 13, 2025
f5bec46
fix tests using register rpc endpoint
bisgaard-itis Oct 13, 2025
366c4b6
propagate usage of preregistration function to api-server
bisgaard-itis Oct 13, 2025
2c8f63b
first attempt at implementing batch patch function job method
bisgaard-itis Oct 14, 2025
308f853
update models
bisgaard-itis Oct 14, 2025
cb9d138
ensure meaningful error message is raised
bisgaard-itis Oct 14, 2025
91eda8d
small fix
bisgaard-itis Oct 14, 2025
d11dd51
add exception in case of unrecoverable error
bisgaard-itis Oct 14, 2025
e959e4d
improve comments
bisgaard-itis Oct 14, 2025
4f1b9b4
improve patch in repository
bisgaard-itis Oct 15, 2025
7f11bab
implement patch function job endpoint
bisgaard-itis Oct 15, 2025
f2c3fb6
fixes
bisgaard-itis Oct 15, 2025
4a3a3bb
minor cleanup
bisgaard-itis Oct 15, 2025
4f2918d
use new patch method in run_function
bisgaard-itis Oct 15, 2025
fa34d1c
propagate task creation all the way out
bisgaard-itis Oct 15, 2025
b0cc3fa
update openapi specs
bisgaard-itis Oct 15, 2025
661bd3a
small change
bisgaard-itis Oct 15, 2025
7804a04
start fixing tests
bisgaard-itis Oct 15, 2025
f4bae45
fix more tests
bisgaard-itis Oct 15, 2025
20088b0
fix yet another test
bisgaard-itis Oct 15, 2025
76a6f6e
fix tests
bisgaard-itis Oct 15, 2025
8f5945c
cleanup
bisgaard-itis Oct 15, 2025
faefeed
🎨 Check study and solver job status before returning output (#8511)
wvangeit Oct 15, 2025
afef308
🎨 Check study and solver job status before returning output (#8511)
wvangeit Oct 15, 2025
2c489ea
clean up imports
bisgaard-itis Oct 15, 2025
2154ff4
several fixes
bisgaard-itis Oct 15, 2025
a5ec531
try to make pylint happy
bisgaard-itis Oct 15, 2025
023b5b1
yet another attempt
bisgaard-itis Oct 15, 2025
12e1ab1
yet another attempt
bisgaard-itis Oct 15, 2025
ce080bd
pylint
bisgaard-itis Oct 15, 2025
54a004a
pylint
bisgaard-itis Oct 15, 2025
5869282
pylint
bisgaard-itis Oct 15, 2025
ee0000d
pylint
bisgaard-itis Oct 15, 2025
472147e
test fixes
bisgaard-itis Oct 16, 2025
786928f
pylint
bisgaard-itis Oct 16, 2025
d4385e5
pylint fix
bisgaard-itis Oct 16, 2025
a0e2a36
Merge branch 'master' into 8506-batch-db-requests-in-map-endpoint
bisgaard-itis Oct 16, 2025
e01a721
Merge branch 'master' into 8506-batch-db-requests-in-map-endpoint
bisgaard-itis Oct 17, 2025
e1d43b6
add register endpoint both for batch operation and for a single input
bisgaard-itis Oct 17, 2025
91fccb8
ensure webserver unit tests pass with new batch operation
bisgaard-itis Oct 17, 2025
38026e3
use batch models/schemas in register function job rpc endpoints
bisgaard-itis Oct 20, 2025
7b38b4d
fix tests
bisgaard-itis Oct 20, 2025
94a7052
start using batch register function jobs in api-server
bisgaard-itis Oct 20, 2025
809964b
clean up
bisgaard-itis Oct 20, 2025
7a68768
improve patch model schema
bisgaard-itis Oct 20, 2025
97993f2
refactor patch method
bisgaard-itis Oct 20, 2025
0ebd500
use patch batch endpoint
bisgaard-itis Oct 20, 2025
650986d
start fixing find_cache method
bisgaard-itis Oct 20, 2025
c3f2755
batch cache endpoints
bisgaard-itis Oct 21, 2025
1e7486a
change requirement for bach get
bisgaard-itis Oct 21, 2025
d5786aa
name change
bisgaard-itis Oct 21, 2025
77b4a5f
use custom signature for batch cache endpoint
bisgaard-itis Oct 21, 2025
d0f3142
fix tests
bisgaard-itis Oct 21, 2025
9f39f70
Merge branch 'master' into 8506-batch-db-requests-in-map-endpoint
bisgaard-itis Oct 21, 2025
e6f289d
remove fcn
bisgaard-itis Oct 21, 2025
5d99508
fix api-server tests
bisgaard-itis Oct 21, 2025
74052c5
pylint
bisgaard-itis Oct 21, 2025
ad85bd9
remove min list length constraint and update openapi specs
bisgaard-itis Oct 21, 2025
43059b8
rename lambda
bisgaard-itis Oct 21, 2025
3dce8b1
remove double FunctionJobCreationTaskStatus import
bisgaard-itis Oct 21, 2025
ade3efe
don't update status when patching job
bisgaard-itis Oct 21, 2025
ee7bb37
status_filter -> cached_job_statuses
bisgaard-itis Oct 21, 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
37 changes: 35 additions & 2 deletions packages/models-library/src/models_library/functions.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import datetime
from collections.abc import Mapping
from enum import Enum
from typing import Annotated, Any, Literal, TypeAlias
from typing import Annotated, Any, Final, Literal, TypeAlias
from uuid import UUID

from models_library import projects
Expand All @@ -23,6 +23,8 @@
FileID: TypeAlias = UUID

InputTypes: TypeAlias = FileID | float | int | bool | str | list
_MIN_LIST_LENGTH: Final[int] = 1
_MAX_LIST_LENGTH: Final[int] = 50


class FunctionSchemaClass(str, Enum):
Expand Down Expand Up @@ -80,9 +82,10 @@ class FunctionClass(str, Enum):

FunctionInputsList: TypeAlias = Annotated[
list[FunctionInputs],
Field(max_length=50),
Field(max_length=_MAX_LIST_LENGTH, min_length=_MIN_LIST_LENGTH),
]


FunctionOutputs: TypeAlias = dict[str, Any] | None

FunctionOutputsLogfile: TypeAlias = Any
Expand Down Expand Up @@ -238,6 +241,9 @@ class RegisteredPythonCodeFunctionJobPatch(BaseModel):
ProjectFunctionJob | PythonCodeFunctionJob | SolverFunctionJob,
Field(discriminator="function_class"),
]
FunctionJobList: TypeAlias = Annotated[
list[FunctionJob], Field(max_length=_MAX_LIST_LENGTH, min_length=_MIN_LIST_LENGTH)
]


class RegisteredFunctionJobBase(FunctionJobBase):
Expand All @@ -263,6 +269,11 @@ class RegisteredPythonCodeFunctionJob(PythonCodeFunctionJob, RegisteredFunctionJ
| RegisteredSolverFunctionJob,
Field(discriminator="function_class"),
]
RegisteredFunctionJobList: TypeAlias = Annotated[
list[RegisteredFunctionJob],
Field(max_length=_MAX_LIST_LENGTH, min_length=_MIN_LIST_LENGTH),
]


RegisteredFunctionJobPatch = Annotated[
RegisteredProjectFunctionJobPatch
Expand All @@ -272,6 +283,28 @@ class RegisteredPythonCodeFunctionJob(PythonCodeFunctionJob, RegisteredFunctionJ
]


class RegisteredProjectFunctionJobPatchInput(BaseModel):
uid: FunctionJobID
patch: RegisteredProjectFunctionJobPatch


RegisteredProjectFunctionJobPatchInputList: TypeAlias = Annotated[
list[RegisteredProjectFunctionJobPatchInput],
Field(max_length=_MAX_LIST_LENGTH, min_length=_MIN_LIST_LENGTH),
]


class RegisteredSolverFunctionJobPatchInput(BaseModel):
uid: FunctionJobID
patch: RegisteredSolverFunctionJobPatch


RegisteredSolverFunctionJobPatchInputList: TypeAlias = Annotated[
list[RegisteredSolverFunctionJobPatchInput],
Field(max_length=_MAX_LIST_LENGTH, min_length=_MIN_LIST_LENGTH),
]


class FunctionJobStatus(BaseModel):
status: str

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,8 @@ class FunctionJobCollectionsExecuteApiAccessDeniedError(FunctionBaseError):
class FunctionJobPatchModelIncompatibleError(FunctionBaseError):
msg_template = "Incompatible patch model for Function '{function_id}' in product '{product_name}'."
status_code: int = 422


class FunctionUnrecoverableError(FunctionBaseError):
msg_template = "Unrecoverable error."
status_code: int = 500
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@
from models_library.functions import (
FunctionClass,
FunctionGroupAccessRights,
FunctionInputsList,
FunctionJobStatus,
FunctionOutputs,
FunctionUserAccessRights,
FunctionUserApiAccessRights,
RegisteredFunctionJobPatch,
RegisteredFunctionJobWithStatus,
RegisteredProjectFunctionJobPatchInputList,
RegisteredSolverFunctionJobPatchInputList,
)
from models_library.products import ProductName
from models_library.rabbitmq_basic_types import RPCMethodName
Expand Down Expand Up @@ -365,19 +367,20 @@ async def patch_registered_function_job(
*,
user_id: UserID,
product_name: ProductName,
function_job_uuid: FunctionJobID,
registered_function_job_patch: RegisteredFunctionJobPatch,
) -> RegisteredFunctionJob:
registered_function_job_patch_inputs: (
RegisteredProjectFunctionJobPatchInputList
| RegisteredSolverFunctionJobPatchInputList
),
) -> list[RegisteredFunctionJob]:
result = await rabbitmq_rpc_client.request(
DEFAULT_WEBSERVER_RPC_NAMESPACE,
TypeAdapter(RPCMethodName).validate_python("patch_registered_function_job"),
user_id=user_id,
product_name=product_name,
function_job_uuid=function_job_uuid,
registered_function_job_patch=registered_function_job_patch,
registered_function_job_patch_inputs=registered_function_job_patch_inputs,
timeout_s=_FUNCTION_RPC_TIMEOUT_SEC,
)
return TypeAdapter(RegisteredFunctionJob).validate_python(
return TypeAdapter(list[RegisteredFunctionJob]).validate_python(
result
) # Validates the result as a RegisteredFunctionJob

Expand Down Expand Up @@ -512,20 +515,20 @@ async def find_cached_function_jobs(
user_id: UserID,
product_name: ProductName,
function_id: FunctionID,
inputs: FunctionInputs,
) -> list[RegisteredFunctionJob] | None:
inputs: FunctionInputsList,
status_filter: list[FunctionJobStatus] | None = None,
) -> list[RegisteredFunctionJob | None]:
result = await rabbitmq_rpc_client.request(
DEFAULT_WEBSERVER_RPC_NAMESPACE,
TypeAdapter(RPCMethodName).validate_python("find_cached_function_jobs"),
function_id=function_id,
inputs=inputs,
status_filter=status_filter,
user_id=user_id,
product_name=product_name,
timeout_s=_FUNCTION_RPC_TIMEOUT_SEC,
)
if result is None:
return None
return TypeAdapter(list[RegisteredFunctionJob]).validate_python(result)
return TypeAdapter(list[RegisteredFunctionJob | None]).validate_python(result)


@log_decorator(_logger, level=logging.DEBUG)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
FunctionID,
FunctionInputs,
FunctionInputSchema,
FunctionJob,
FunctionJobCollection,
FunctionJobCollectionID,
FunctionJobCollectionsListFilters,
Expand All @@ -20,12 +19,17 @@
from models_library.functions import (
FunctionClass,
FunctionGroupAccessRights,
FunctionInputsList,
FunctionJob,
FunctionJobList,
FunctionJobStatus,
FunctionOutputs,
FunctionUserAccessRights,
FunctionUserApiAccessRights,
RegisteredFunctionJobPatch,
RegisteredFunctionJobList,
RegisteredFunctionJobWithStatus,
RegisteredProjectFunctionJobPatchInputList,
RegisteredSolverFunctionJobPatchInputList,
)
from models_library.products import ProductName
from models_library.rabbitmq_basic_types import RPCNamespace
Expand Down Expand Up @@ -329,22 +333,40 @@ async def register_function_job(
),
)

async def register_function_job_batch(
self,
*,
product_name: ProductName,
user_id: UserID,
function_jobs: FunctionJobList,
) -> RegisteredFunctionJobList:
"""Register a function job."""
return TypeAdapter(RegisteredFunctionJobList).validate_python(
await self._request(
"register_function_job_batch",
product_name=product_name,
user_id=user_id,
function_jobs=function_jobs,
),
)

async def patch_registered_function_job(
self,
*,
product_name: ProductName,
user_id: UserID,
function_job_uuid: FunctionJobID,
registered_function_job_patch: RegisteredFunctionJobPatch,
) -> RegisteredFunctionJob:
registered_function_job_patch_inputs: (
RegisteredProjectFunctionJobPatchInputList
| RegisteredSolverFunctionJobPatchInputList
),
) -> list[RegisteredFunctionJob]:
"""Patch a registered function job."""
return TypeAdapter(RegisteredFunctionJob).validate_python(
return TypeAdapter(list[RegisteredFunctionJob]).validate_python(
await self._request(
"patch_registered_function_job",
product_name=product_name,
user_id=user_id,
function_job_uuid=function_job_uuid,
registered_function_job_patch=registered_function_job_patch,
registered_function_job_patch_inputs=registered_function_job_patch_inputs,
),
)

Expand Down Expand Up @@ -462,16 +484,18 @@ async def find_cached_function_jobs(
product_name: ProductName,
user_id: UserID,
function_id: FunctionID,
inputs: FunctionInputs,
) -> list[RegisteredFunctionJob] | None:
inputs: FunctionInputsList,
status_filter: list[FunctionJobStatus] | None = None,
) -> list[RegisteredFunctionJob | None]:
"""Find cached function jobs."""
return TypeAdapter(list[RegisteredFunctionJob] | None).validate_python(
return TypeAdapter(list[RegisteredFunctionJob | None]).validate_python(
await self._request(
"find_cached_function_jobs",
product_name=product_name,
user_id=user_id,
function_id=function_id,
inputs=inputs,
status_filter=status_filter,
),
)

Expand Down
1 change: 1 addition & 0 deletions services/api-server/openapi.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"openapi": "3.1.0",
"info": {
Expand Down Expand Up @@ -8240,6 +8240,7 @@
}
]
},
"minItems": 1,
"maxItems": 50,
"title": "Function Inputs List"
}
Expand Down
Loading
Loading