Skip to content

fix: Kernel - FaceActions - check if batch is available on server - if available use batch project _fill_bodies #656

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jul 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions doc/changelog.d/656.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Kernel - faceactions - check if batch is available on server - if available use batch project _fill_bodies
50 changes: 46 additions & 4 deletions src/ansys/speos/core/kernel/face.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,13 @@

from typing import Iterator, List

from grpc import RpcError

from ansys.api.speos.part.v1 import (
face_pb2 as messages,
face_pb2_grpc as service,
)
from ansys.speos.core.generic.general_methods import min_speos_version
from ansys.speos.core.kernel.crud import CrudItem, CrudStub
from ansys.speos.core.kernel.proto_message_utils import protobuf_message_to_str

Expand Down Expand Up @@ -102,7 +105,19 @@ class FaceStub(CrudStub):
def __init__(self, channel):
super().__init__(stub=service.FacesManagerStub(channel=channel))
self._actions_stub = service.FaceActionsStub(channel=channel)

self._is_batch_available = self._check_if_batch_available()

def _check_if_batch_available(self) -> bool:
try:
for reserve_faces_res in self._actions_stub.ReserveFaces(
FaceStub._reserve_face_iterator([ProtoFace(name="tmp")])
):
FaceLink(self, reserve_faces_res.guids[0]).delete()
return True
except RpcError:
return False

@min_speos_version(25, 2, 0)
def create_batch(self, message_list: List[ProtoFace]) -> List[FaceLink]:
"""Create new entries.

Expand All @@ -116,6 +131,9 @@ def create_batch(self, message_list: List[ProtoFace]) -> List[FaceLink]:
List[ansys.speos.core.kernel.face.FaceLink]
List pf link objects created.
"""
if not self._is_batch_available:
raise NotImplementedError("Please use a Speos Version of 2025 R2 SP0 or higher.")

reserve_faces_res = self._actions_stub.ReserveFaces(
FaceStub._reserve_face_iterator(message_list)
)
Expand Down Expand Up @@ -145,8 +163,15 @@ def create(self, message: ProtoFace) -> FaceLink:
ansys.speos.core.kernel.face.FaceLink
Link object created.
"""
return self.create_batch(message_list=[message])[0]
resp = CrudStub.create(self, messages.Create_Request(face=ProtoFace(name="tmp")))

chunk_iterator = FaceStub._faces_to_chunks(
guids=[resp.guid], message_list=[message], nb_items=128 * 1024
)
self._actions_stub.Upload(chunk_iterator)
return FaceLink(self, resp.guid)

@min_speos_version(25, 2, 0)
def read_batch(self, refs: List[FaceLink]) -> List[ProtoFace]:
"""Get existing entries.

Expand All @@ -160,6 +185,9 @@ def read_batch(self, refs: List[FaceLink]) -> List[ProtoFace]:
List[face.Face]
Datamodels of the entries.
"""
if not self._is_batch_available:
raise NotImplementedError("Please use a Speos Version of 2025 R2 SP0 or higher.")

for ref in refs:
if not ref.stub == self:
raise ValueError("FaceLink is not on current database. Key=" + ref.key)
Expand All @@ -181,8 +209,13 @@ def read(self, ref: FaceLink) -> ProtoFace:
face.Face
Datamodel of the entry.
"""
return self.read_batch(refs=[ref])[0]
if not ref.stub == self:
raise ValueError("FaceLink is not on current database. Key=" + ref.key)

chunks = self._actions_stub.Download(request=messages.Download_Request(guid=ref.key))
return FaceStub._chunks_to_faces(chunks)[0]

@min_speos_version(25, 2, 0)
def update_batch(self, refs: List[FaceLink], data: List[ProtoFace]) -> None:
"""Change existing entries.

Expand All @@ -194,6 +227,9 @@ def update_batch(self, refs: List[FaceLink], data: List[ProtoFace]) -> None:
data : List[face.Face]
New datamodels for the entries.
"""
if not self._is_batch_available:
raise NotImplementedError("Please use a Speos Version of 2025 R2 SP0 or higher.")

for ref in refs:
if not ref.stub == self:
raise ValueError("FaceLink is not on current database")
Expand All @@ -214,7 +250,13 @@ def update(self, ref: FaceLink, data: ProtoFace) -> None:
data : face.Face
New datamodel for the entry.
"""
self.update_batch(refs=[ref], data=[data])
if not ref.stub == self:
raise ValueError("FaceLink is not on current database")

chunk_iterator = FaceStub._faces_to_chunks(
guids=[ref.key], message_list=[data], nb_items=128 * 1024
)
self._actions_stub.Upload(chunk_iterator)

def delete(self, ref: FaceLink) -> None:
"""Remove an existing entry.
Expand Down
25 changes: 18 additions & 7 deletions src/ansys/speos/core/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -691,14 +691,25 @@ def _fill_bodies(
b_feat = feat_host.create_body(name=b_data.name)
b_feat.body_link = b_link
b_feat._body = b_data # instead of b_feat.reset() - this avoid a useless read in server

f_links = self.client.get_items(keys=b_data.face_guids, item_type=FaceLink)
for f_link in f_links:
f_data = f_link.get()
f_feat = b_feat.create_face(name=f_data.name)
f_feat.face_link = f_link
f_feat._face = (
f_data # instead of f_feat.reset() - this avoid a useless read in server
)
face_db = self.client.faces()
if face_db._is_batch_available:
f_data_list = face_db.read_batch(refs=f_links)
for f_data, f_link in zip(f_data_list, f_links):
f_feat = b_feat.create_face(name=f_data.name)
f_feat.face_link = f_link
f_feat._face = (
f_data # instead of f_feat.reset() - this avoid a useless read in server
)
else:
for f_link in f_links:
f_data = f_link.get()
f_feat = b_feat.create_face(name=f_data.name)
f_feat.face_link = f_link
f_feat._face = (
f_data # instead of f_feat.reset() - this avoid a useless read in server
)

def _add_unique_ids(self):
scene_data = self.scene_link.get()
Expand Down
1 change: 1 addition & 0 deletions tests/core/test_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,7 @@ def test_preview_visual_data(speos: Speos):
p2.preview()
# preview when there is no cad
p3 = Project(speos=speos)
p3.create_root_part().commit() # Needed for 251 server.
sr = p3.create_source(name="Luminaire_source.2", feature_type=SourceLuminaire)
sr.set_intensity_file_uri(uri=str(Path(test_path) / "IES_C_DETECTOR.ies"))
sr.commit()
Expand Down
6 changes: 3 additions & 3 deletions tests/kernel/test_geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def test_create_big_face(speos: Speos):


def test_create_big_faces(speos: Speos):
"""Test create big faces using batch."""
"""Test create big faces using batch. Only available from SpeosRPC_Server 25.2."""
assert speos.client.healthy is True
# Get DB
face_db = speos.client.faces() # Create face stub from client channel
Expand Down Expand Up @@ -124,7 +124,7 @@ def test_create_big_faces(speos: Speos):


def test_update_big_face(speos: Speos):
"""Test update big face."""
"""Test update big face. Bug on SpeosRPC_Server 25.1. Fixed from SpeosRPC_Server 25.2."""
assert speos.client.healthy is True
# Get DB
face_db = speos.client.faces() # Create face stub from client channel
Expand Down Expand Up @@ -175,7 +175,7 @@ def test_update_big_face(speos: Speos):


def test_update_big_faces(speos: Speos):
"""Test update big faces using batch."""
"""Test update big faces using batch. Only available from SpeosRPC_Server 25.2."""
assert speos.client.healthy is True
# Get DB
face_db = speos.client.faces() # Create face stub from client channel
Expand Down