Skip to content

Commit e9eec69

Browse files
🐛 Sync nodes when patching (#6973)
1 parent 48d3fba commit e9eec69

File tree

2 files changed

+92
-4
lines changed

2 files changed

+92
-4
lines changed

services/web/server/src/simcore_service_webserver/projects/projects_api.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,13 +1047,17 @@ async def patch_project_node(
10471047
if _node_patch_exclude_unset.get("label"):
10481048
await dynamic_scheduler_api.update_projects_networks(app, project_id=project_id)
10491049

1050-
# 5. Updates project states for user, if inputs have been changed
1051-
if "inputs" in _node_patch_exclude_unset:
1050+
# 5. Updates project states for user, if inputs/outputs have been changed
1051+
if {"inputs", "outputs"} & _node_patch_exclude_unset.keys():
10521052
updated_project = await add_project_states_for_user(
10531053
user_id=user_id, project=updated_project, is_template=False, app=app
10541054
)
1055+
for node_uuid in updated_project["workbench"]:
1056+
await notify_project_node_update(
1057+
app, updated_project, node_uuid, errors=None
1058+
)
1059+
return
10551060

1056-
# 6. Notify project node update
10571061
await notify_project_node_update(app, updated_project, node_id, errors=None)
10581062

10591063

services/web/server/tests/unit/with_dbs/02/test_projects_nodes_handlers__patch.py

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ def mock_catalog_rpc_check_for_service(mocker: MockerFixture):
5353
)
5454

5555

56+
@pytest.fixture
57+
def mocked_notify_project_node_update(mocker: MockerFixture):
58+
return mocker.patch(
59+
"simcore_service_webserver.projects.projects_api.notify_project_node_update",
60+
)
61+
62+
5663
@pytest.mark.parametrize(
5764
"user_role,expected",
5865
[
@@ -195,7 +202,7 @@ async def test_patch_project_node(
195202
_tested_node = data["workbench"][node_id]
196203

197204
assert _tested_node["label"] == "testing-string"
198-
assert _tested_node["progress"] == None
205+
assert _tested_node["progress"] is None
199206
assert _tested_node["key"] == _patch_key["key"]
200207
assert _tested_node["version"] == _patch_version["version"]
201208
assert _tested_node["inputs"] == _patch_inputs["inputs"]
@@ -205,6 +212,83 @@ async def test_patch_project_node(
205212
assert _tested_node["outputs"] == _patch_outputs["outputs"]
206213

207214

215+
@pytest.mark.parametrize(
216+
"user_role,expected", [(UserRole.USER, status.HTTP_204_NO_CONTENT)]
217+
)
218+
async def test_patch_project_node_notifies(
219+
mocker: MockerFixture,
220+
client: TestClient,
221+
logged_user: UserInfoDict,
222+
user_project: ProjectDict,
223+
expected: HTTPStatus,
224+
mock_catalog_api_get_services_for_user_in_product,
225+
mock_project_uses_available_services,
226+
mock_catalog_rpc_check_for_service,
227+
mocked_notify_project_node_update,
228+
):
229+
230+
node_id = next(iter(user_project["workbench"]))
231+
assert client.app
232+
base_url = client.app.router["patch_project_node"].url_for(
233+
project_id=user_project["uuid"], node_id=node_id
234+
)
235+
236+
# inputs
237+
_patch_inputs = {
238+
"key": "simcore/services/dynamic/patch-service-key",
239+
}
240+
resp = await client.patch(
241+
f"{base_url}",
242+
data=json.dumps(_patch_inputs),
243+
)
244+
await assert_status(resp, expected)
245+
assert mocked_notify_project_node_update.call_count == 1
246+
args = mocked_notify_project_node_update.await_args_list
247+
assert args[0][0][1]["workbench"][node_id]["key"] == _patch_inputs["key"]
248+
assert f"{args[0][0][2]}" == node_id
249+
250+
251+
@pytest.mark.parametrize(
252+
"user_role,expected", [(UserRole.USER, status.HTTP_204_NO_CONTENT)]
253+
)
254+
async def test_patch_project_node_inputs_notifies(
255+
mocker: MockerFixture,
256+
client: TestClient,
257+
logged_user: UserInfoDict,
258+
user_project: ProjectDict,
259+
expected: HTTPStatus,
260+
mock_catalog_api_get_services_for_user_in_product,
261+
mock_project_uses_available_services,
262+
mocked_notify_project_node_update,
263+
):
264+
node_id = next(iter(user_project["workbench"]))
265+
assert client.app
266+
base_url = client.app.router["patch_project_node"].url_for(
267+
project_id=user_project["uuid"], node_id=node_id
268+
)
269+
270+
# inputs
271+
_patch_inputs = {
272+
"inputs": {
273+
"input_1": {
274+
"nodeUuid": "c374e5ba-fc42-5c40-ae74-df7ef337f597",
275+
"output": "out_1",
276+
},
277+
}
278+
}
279+
resp = await client.patch(
280+
f"{base_url}",
281+
data=json.dumps(_patch_inputs),
282+
)
283+
await assert_status(resp, expected)
284+
assert mocked_notify_project_node_update.call_count > 1
285+
# 1 message per node updated
286+
assert [
287+
call_args[0][2]
288+
for call_args in mocked_notify_project_node_update.await_args_list
289+
] == list(user_project["workbench"].keys())
290+
291+
208292
@pytest.mark.parametrize(
209293
"user_role,expected", [(UserRole.USER, status.HTTP_204_NO_CONTENT)]
210294
)

0 commit comments

Comments
 (0)