Skip to content

Commit 0c4abd7

Browse files
committed
Enhance logging descriptions in request methods to include component class name and target name; update documentation for message handling in BusinessProcess
1 parent c551f62 commit 0c4abd7

3 files changed

Lines changed: 222 additions & 209 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2222
- Strengthen application skills with a complete ingestion-pipeline architecture,
2323
container-backed runtime verification, non-blocking start and log commands,
2424
and IoP CLI-first operational checks.
25+
- Default description values for `send_request_sync()`, `send_request_async()`,
26+
`send_request_async_ng()`, and `send_generator_request()` to include the
27+
calling component class name and target name.
2528

2629
### Fixed
2730
- Prevent concurrent `send_request_async_ng()` calls from livelocking when

src/iop/components/business_host.py

Lines changed: 85 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ def _resolve_attribute_target(host: Any, node: ast.Attribute) -> Any:
8484
return _UNRESOLVED
8585
value = getattr(value, attr, _UNRESOLVED)
8686
return value
87-
88-
87+
88+
8989
class _BusinessHost(_Common):
9090
"""Base class for business components that defines common methods.
9191
@@ -95,12 +95,12 @@ class _BusinessHost(_Common):
9595
as self.Output instead of hard-coded component names. See
9696
docs/cookbooks/production-settings-and-targets.md.
9797
"""
98-
99-
buffer: int = 64000
100-
DISPATCH: list[tuple[str, str]] = []
101-
102-
@input_serializer_param(1, "request")
103-
@output_deserializer
98+
99+
buffer: int = 64000
100+
DISPATCH: list[tuple[str, str]] = []
101+
102+
@input_serializer_param(1, "request")
103+
@output_deserializer
104104
def send_request_sync(
105105
self,
106106
target: str | TargetSettingRef,
@@ -134,11 +134,13 @@ def send_request_sync(
134134
docs/cookbooks/production-settings-and-targets.md
135135
"""
136136
target = resolve_target(target)
137+
if description is None:
138+
description = f"{self.__class__.__name__} -> {target}"
137139
return self.iris_handle.dispatchSendRequestSync(
138140
target, request, timeout, description
139141
)
140-
141-
@input_serializer_param(1, "request")
142+
143+
@input_serializer_param(1, "request")
142144
def send_request_async(
143145
self,
144146
target: str | TargetSettingRef,
@@ -170,6 +172,8 @@ def send_request_async(
170172
docs/cookbooks/production-settings-and-targets.md
171173
"""
172174
target = resolve_target(target)
175+
if description is None:
176+
description = f"{self.__class__.__name__} -> {target}"
173177
return self.iris_handle.dispatchSendRequestAsync(target, request, description)
174178

175179
async def send_request_async_ng(
@@ -186,14 +190,16 @@ async def send_request_async_ng(
186190
187191
Args:
188192
target: Name of target component
189-
request: Message to send
190-
timeout: Timeout in seconds, -1 means wait forever
191-
description: Optional description for logging
192-
193+
request: Message to send
194+
timeout: Timeout in seconds, -1 means wait forever
195+
description: Optional description for logging
196+
193197
Returns:
194198
Response from target component
195199
"""
196200
target = cast(str, resolve_target(target))
201+
if description is None:
202+
description = f"{self.__class__.__name__} -> {target}"
197203
return await AsyncRequest(target, request, timeout, description, self)
198204

199205
def send_generator_request(
@@ -211,14 +217,16 @@ def send_generator_request(
211217
Args:
212218
target: Name of target component
213219
request: Message to send
214-
timeout: Timeout in seconds, -1 means wait forever
215-
description: Optional description for logging
216-
Returns:
217-
_GeneratorRequest: An instance of _GeneratorRequest to iterate over responses
220+
timeout: Timeout in seconds, -1 means wait forever
221+
description: Optional description for logging
222+
Returns:
223+
_GeneratorRequest: An instance of _GeneratorRequest to iterate over responses
218224
Raises:
219225
TypeError: If request is not of type Message
220226
"""
221227
target = cast(str, resolve_target(target))
228+
if description is None:
229+
description = f"{self.__class__.__name__} -> {target}"
222230
return _GeneratorRequest(self, target, request, timeout, description)
223231

224232
def send_multi_request_sync(
@@ -235,13 +243,13 @@ def send_multi_request_sync(
235243
236244
Args:
237245
target_request: List of tuples (target, request) to send
238-
timeout: Timeout in seconds, -1 means wait forever
239-
description: Optional description for logging
240-
241-
Returns:
242-
List of tuples (target, request, response, status)
243-
244-
Raises:
246+
timeout: Timeout in seconds, -1 means wait forever
247+
description: Optional description for logging
248+
249+
Returns:
250+
List of tuples (target, request, response, status)
251+
252+
Raises:
245253
TypeError: If target_request is not a list of tuples
246254
ValueError: If target_request is empty
247255
"""
@@ -254,11 +262,11 @@ def send_multi_request_sync(
254262
self._create_call_structure(target, request)
255263
for target, request in resolved_target_request
256264
]
257-
258-
response_list = self.iris_handle.dispatchSendRequestSyncMultiple(
259-
call_list, timeout
260-
)
261-
265+
266+
response_list = self.iris_handle.dispatchSendRequestSyncMultiple(
267+
call_list, timeout
268+
)
269+
262270
return [
263271
(
264272
resolved_target_request[i][0],
@@ -268,20 +276,20 @@ def send_multi_request_sync(
268276
)
269277
for i in range(len(resolved_target_request))
270278
]
271-
279+
272280
def _validate_target_request(
273281
self, target_request: list[tuple[str | TargetSettingRef, Message | Any]]
274282
) -> None:
275-
"""Validate the target_request parameter structure."""
276-
if not isinstance(target_request, list):
277-
raise TypeError("target_request must be a list")
278-
if not target_request:
279-
raise ValueError("target_request must not be empty")
280-
if not all(
281-
isinstance(item, tuple) and len(item) == 2 for item in target_request
282-
):
283-
raise TypeError("target_request must contain tuples of (target, request)")
284-
283+
"""Validate the target_request parameter structure."""
284+
if not isinstance(target_request, list):
285+
raise TypeError("target_request must be a list")
286+
if not target_request:
287+
raise ValueError("target_request must not be empty")
288+
if not all(
289+
isinstance(item, tuple) and len(item) == 2 for item in target_request
290+
):
291+
raise TypeError("target_request must contain tuples of (target, request)")
292+
285293
def _create_call_structure(
286294
self, target: str | TargetSettingRef, request: Message | Any
287295
) -> Any:
@@ -291,34 +299,34 @@ def _create_call_structure(
291299
call.TargetDispatchName = resolve_target(target)
292300
call.Request = dispatch_serializer(request)
293301
return call
294-
295-
@staticmethod
296-
def OnGetConnections() -> list[str] | None:
302+
303+
@staticmethod
304+
def OnGetConnections() -> list[str] | None:
297305
"""Return all configured targets for this class.
298306
299307
Implement this method to allow connections between components to show up
300308
in the interoperability UI.
301-
302-
Returns:
303-
An IRISList containing all targets for this class. Default is None.
304-
"""
305-
return None
306-
309+
310+
Returns:
311+
An IRISList containing all targets for this class. Default is None.
312+
"""
313+
return None
314+
307315
@staticmethod
308316
def get_adapter_type() -> str | None:
309-
"""Returns the name of the registered Adapter.
310-
311-
Returns:
312-
Name of the registered Adapter
313-
"""
314-
return
315-
317+
"""Returns the name of the registered Adapter.
318+
319+
Returns:
320+
Name of the registered Adapter
321+
"""
322+
return
323+
316324
def on_get_connections(self) -> list[str]:
317325
"""Return targets found in send_request_sync and send_request_async calls.
318326
319327
Implement this method to allow connections between components to show up
320328
in the interoperability UI.
321-
329+
322330
Returns:
323331
A list containing all targets for this class.
324332
"""
@@ -341,23 +349,23 @@ def on_get_connections(self) -> list[str]:
341349
target_list.append(target)
342350

343351
return target_list
344-
345-
@input_deserializer
346-
def _dispatch_generator_started(self, request: Any) -> Any:
347-
"""For internal use only."""
352+
353+
@input_deserializer
354+
def _dispatch_generator_started(self, request: Any) -> Any:
355+
"""For internal use only."""
348356
self._gen = dispatch_message(self, request)
349-
# check if self._gen is a generator
350-
if not hasattr(self._gen, "__iter__"):
351-
raise TypeError(
352-
f"Expected a generator or iterable object, got: {type(self._gen).__name__}"
353-
)
354-
355-
return _iris.get_iris().IOP.Generator.Message.Ack._New()
356-
357-
@output_serializer
358-
def _dispatch_generator_poll(self) -> Any:
359-
"""For internal use only."""
360-
try:
361-
return next(self._gen)
362-
except StopIteration:
363-
return _iris.get_iris().IOP.Generator.Message.Stop._New()
357+
# check if self._gen is a generator
358+
if not hasattr(self._gen, "__iter__"):
359+
raise TypeError(
360+
f"Expected a generator or iterable object, got: {type(self._gen).__name__}"
361+
)
362+
363+
return _iris.get_iris().IOP.Generator.Message.Ack._New()
364+
365+
@output_serializer
366+
def _dispatch_generator_poll(self) -> Any:
367+
"""For internal use only."""
368+
try:
369+
return next(self._gen)
370+
except StopIteration:
371+
return _iris.get_iris().IOP.Generator.Message.Stop._New()

0 commit comments

Comments
 (0)