Skip to content

Commit 616bf69

Browse files
committed
Changes based on Mads comments wrt functions api
1 parent d246bb4 commit 616bf69

File tree

4 files changed

+104
-45
lines changed

4 files changed

+104
-45
lines changed

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

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818

1919
class FunctionSchema(BaseModel):
20+
"""Schema for function input/output"""
21+
2022
schema_dict: dict[str, Any] | None # JSON Schema
2123

2224

@@ -163,3 +165,52 @@ class FunctionJobCollectionDB(BaseModel):
163165

164166
class FunctionJobCollectionStatus(BaseModel):
165167
status: list[str]
168+
169+
170+
class FunctionNotFoundError(Exception):
171+
"""Exception raised when a function is not found"""
172+
173+
def __init__(self, function_id: FunctionID):
174+
self.function_id = function_id
175+
super().__init__(f"Function {function_id} not found")
176+
177+
178+
class FunctionJobNotFoundError(Exception):
179+
"""Exception raised when a function job is not found"""
180+
181+
def __init__(self, function_job_id: FunctionJobID):
182+
self.function_job_id = function_job_id
183+
super().__init__(f"Function job {function_job_id} not found")
184+
185+
186+
class FunctionJobCollectionNotFoundError(Exception):
187+
"""Exception raised when a function job collection is not found"""
188+
189+
def __init__(self, function_job_collection_id: FunctionJobCollectionID):
190+
self.function_job_collection_id = function_job_collection_id
191+
super().__init__(
192+
f"Function job collection {function_job_collection_id} not found"
193+
)
194+
195+
196+
class RegisterFunctionWithUIDError(Exception):
197+
"""Exception raised when registering a function with a UID"""
198+
199+
def __init__(self):
200+
super().__init__("Cannot register Function with a UID")
201+
202+
203+
class UnsupportedFunctionClassError(Exception):
204+
"""Exception raised when a function class is not supported"""
205+
206+
def __init__(self, function_class: str):
207+
self.function_class = function_class
208+
super().__init__(f"Function class {function_class} is not supported")
209+
210+
211+
class UnsupportedFunctionJobClassError(Exception):
212+
"""Exception raised when a function job class is not supported"""
213+
214+
def __init__(self, function_job_class: str):
215+
self.function_job_class = function_job_class
216+
super().__init__(f"Function job class {function_job_class} is not supported")

services/web/server/src/simcore_service_webserver/functions/_functions_controller_rpc.py

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
ProjectFunctionJob,
1919
SolverFunction,
2020
SolverFunctionJob,
21+
UnsupportedFunctionClassError,
22+
UnsupportedFunctionJobClassError,
2123
)
2224
from models_library.rest_pagination import (
2325
PageMetaInfoLimitOffset,
@@ -32,12 +34,6 @@
3234
# pylint: disable=no-else-return
3335

3436

35-
@router.expose()
36-
async def ping(app: web.Application) -> str:
37-
assert app
38-
return "pong from webserver"
39-
40-
4137
@router.expose()
4238
async def register_function(app: web.Application, *, function: Function) -> Function:
4339
assert app
@@ -72,8 +68,7 @@ def _decode_function(
7268
default_inputs=function.default_inputs,
7369
)
7470
else:
75-
msg = f"Unsupported function class: [{function.function_class}]"
76-
raise TypeError(msg)
71+
raise UnsupportedFunctionClassError(function_class=function.function_class)
7772

7873

7974
def _encode_function(
@@ -91,8 +86,7 @@ def _encode_function(
9186
}
9287
)
9388
else:
94-
msg = f"Unsupported function class: {function.function_class}"
95-
raise TypeError(msg)
89+
raise UnsupportedFunctionClassError(function_class=function.function_class)
9690

9791
return FunctionDB(
9892
uuid=function.uid,
@@ -142,8 +136,9 @@ def _decode_functionjob(
142136
solver_job_id=functionjob_db.class_specific_data["solver_job_id"],
143137
)
144138
else:
145-
msg = f"Unsupported function class: [{functionjob_db.function_class}]"
146-
raise TypeError(msg)
139+
raise UnsupportedFunctionJobClassError(
140+
function_job_class=functionjob_db.function_class
141+
)
147142

148143

149144
def _encode_functionjob(
@@ -178,8 +173,9 @@ def _encode_functionjob(
178173
function_class=functionjob.function_class,
179174
)
180175
else:
181-
msg = f"Unsupported function class: [{functionjob.function_class}]"
182-
raise TypeError(msg)
176+
raise UnsupportedFunctionJobClassError(
177+
function_job_class=functionjob.function_class
178+
)
183179

184180

185181
@router.expose()
@@ -355,8 +351,9 @@ async def find_cached_function_job(
355351
solver_job_id=returned_function_job.class_specific_data["solver_job_id"],
356352
)
357353
else:
358-
msg = f"Unsupported function class: [{returned_function_job.function_class}]"
359-
raise TypeError(msg)
354+
raise UnsupportedFunctionJobClassError(
355+
function_job_class=returned_function_job.function_class
356+
)
360357

361358

362359
@router.expose()

services/web/server/src/simcore_service_webserver/functions/_functions_repository.py

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,12 @@
77
FunctionInputs,
88
FunctionJobCollection,
99
FunctionJobCollectionDB,
10+
FunctionJobCollectionNotFoundError,
1011
FunctionJobDB,
1112
FunctionJobID,
13+
FunctionJobNotFoundError,
14+
FunctionNotFoundError,
15+
RegisterFunctionWithUIDError,
1216
)
1317
from models_library.rest_pagination import (
1418
PageMetaInfoLimitOffset,
@@ -52,8 +56,7 @@ async def register_function(
5256
) -> FunctionDB:
5357

5458
if function.uuid is not None:
55-
msg = "Function uid is not None. Cannot register function."
56-
raise ValueError(msg)
59+
raise RegisterFunctionWithUIDError
5760

5861
async with transaction_context(get_asyncpg_engine(app), connection) as conn:
5962
result = await conn.stream(
@@ -79,9 +82,10 @@ async def register_function(
7982
)
8083
row = await result.first()
8184

82-
if row is None:
83-
msg = "No row was returned from the database after creating function."
84-
raise ValueError(msg)
85+
assert row is not None, (
86+
"No row was returned from the database after creating function."
87+
f" Function: {function}"
88+
) # nosec
8589

8690
return FunctionDB.model_validate(dict(row))
8791

@@ -100,9 +104,7 @@ async def get_function(
100104
row = await result.first()
101105

102106
if row is None:
103-
msg = f"No function found with id {function_id}."
104-
raise web.HTTPNotFound(reason=msg)
105-
107+
raise FunctionNotFoundError(function_id=function_id)
106108
return FunctionDB.model_validate(dict(row))
107109

108110

@@ -258,9 +260,10 @@ async def register_function_job(
258260
)
259261
row = await result.first()
260262

261-
if row is None:
262-
msg = "No row was returned from the database after creating function job."
263-
raise ValueError(msg)
263+
assert row is not None, (
264+
"No row was returned from the database after creating function job."
265+
f" Function job: {function_job}"
266+
) # nosec
264267

265268
return FunctionJobDB.model_validate(dict(row))
266269

@@ -281,8 +284,7 @@ async def get_function_job(
281284
row = await result.first()
282285

283286
if row is None:
284-
msg = f"No function job found with id {function_job_id}."
285-
raise web.HTTPNotFound(reason=msg)
287+
raise FunctionJobNotFoundError(function_job_id=function_job_id)
286288

287289
return FunctionJobDB.model_validate(dict(row))
288290

@@ -319,13 +321,19 @@ async def find_cached_function_job(
319321

320322
rows = await result.all()
321323

322-
if rows is None:
324+
if rows is None or len(rows) == 0:
323325
return None
324326

325-
for row in rows:
326-
job = FunctionJobDB.model_validate(dict(row))
327-
if job.inputs == inputs:
328-
return job
327+
assert len(rows) == 1, (
328+
"More than one function job found with the same function id and inputs."
329+
f" Function id: {function_id}, Inputs: {inputs}"
330+
) # nosec
331+
332+
row = rows[0]
333+
334+
job = FunctionJobDB.model_validate(dict(row))
335+
if job.inputs == inputs:
336+
return job
329337

330338
return None
331339

@@ -346,8 +354,9 @@ async def get_function_job_collection(
346354
row = await result.first()
347355

348356
if row is None:
349-
msg = f"No function job collection found with id {function_job_collection_id}."
350-
raise web.HTTPNotFound(reason=msg)
357+
raise FunctionJobCollectionNotFoundError(
358+
function_job_collection_id=function_job_collection_id
359+
)
351360

352361
# Retrieve associated job ids from the join table
353362
job_result = await conn.stream(
@@ -383,9 +392,10 @@ async def register_function_job_collection(
383392
)
384393
row = await result.first()
385394

386-
if row is None:
387-
msg = "No row was returned from the database after creating function job collection."
388-
raise ValueError(msg)
395+
assert row is not None, (
396+
"No row was returned from the database after creating function job collection."
397+
f" Function job collection: {function_job_collection}"
398+
) # nosec
389399

390400
for job_id in function_job_collection.job_ids:
391401
await conn.execute(

services/web/server/tests/unit/with_dbs/functions_rpc/test_functions_controller_rpc.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33

44
import pytest
55
import simcore_service_webserver.functions._functions_controller_rpc as functions_rpc
6-
from aiohttp import web
76
from models_library.api_schemas_webserver.functions_wb_schema import (
87
Function,
98
FunctionInputSchema,
109
FunctionJobCollection,
10+
FunctionJobNotFoundError,
11+
FunctionNotFoundError,
1112
FunctionOutputSchema,
1213
ProjectFunction,
1314
ProjectFunctionJob,
@@ -89,7 +90,7 @@ async def test_get_function(client, mock_function):
8990
@pytest.mark.asyncio
9091
async def test_get_function_not_found(client):
9192
# Attempt to retrieve a function that does not exist
92-
with pytest.raises(web.HTTPNotFound):
93+
with pytest.raises(FunctionNotFoundError):
9394
await functions_rpc.get_function(app=client.app, function_id=uuid4())
9495

9596

@@ -225,7 +226,7 @@ async def test_delete_function(client, mock_function):
225226
)
226227

227228
# Attempt to retrieve the deleted function
228-
with pytest.raises(web.HTTPNotFound):
229+
with pytest.raises(FunctionNotFoundError):
229230
await functions_rpc.get_function(
230231
app=client.app, function_id=registered_function.uid
231232
)
@@ -298,7 +299,7 @@ async def test_get_function_job(client, mock_function):
298299
@pytest.mark.asyncio
299300
async def test_get_function_job_not_found(client):
300301
# Attempt to retrieve a function job that does not exist
301-
with pytest.raises(web.HTTPNotFound):
302+
with pytest.raises(FunctionJobNotFoundError):
302303
await functions_rpc.get_function_job(app=client.app, function_job_id=uuid4())
303304

304305

@@ -365,7 +366,7 @@ async def test_delete_function_job(client, mock_function):
365366
)
366367

367368
# Attempt to retrieve the deleted job
368-
with pytest.raises(web.HTTPNotFound):
369+
with pytest.raises(FunctionJobNotFoundError):
369370
await functions_rpc.get_function_job(
370371
app=client.app, function_job_id=registered_job.uid
371372
)
@@ -427,7 +428,7 @@ async def test_function_job_collection(client, mock_function):
427428
app=client.app, function_job_collection_id=registered_collection.uid
428429
)
429430
# Attempt to retrieve the deleted collection
430-
with pytest.raises(web.HTTPNotFound):
431+
with pytest.raises(FunctionJobNotFoundError):
431432
await functions_rpc.get_function_job(
432433
app=client.app, function_job_id=registered_collection.uid
433434
)

0 commit comments

Comments
 (0)