mirror of
https://github.com/Horizontal42/netsleuth.git
synced 2026-11-11 01:02:10 +03:00
docs: add comprehensive docstrings to orchestration module
- Add docstring to utc_now_iso() explaining return format - Add docstring to classify_exception() with args, returns, and examples - Add docstring to run_module() detailing timeout and error handling behavior - Add docstring to gather_modules() describing concurrent execution semantics
This commit is contained in:
parent
e6cbe1b4ab
commit
310404bceb
1 changed files with 59 additions and 0 deletions
|
|
@ -14,10 +14,34 @@ _RETRYABLE_STATUS_FLOOR = 500
|
||||||
|
|
||||||
|
|
||||||
def utc_now_iso() -> str:
|
def utc_now_iso() -> str:
|
||||||
|
"""Return the current UTC timestamp in ISO 8601 format.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A string like '2025-01-15T14:30:00Z' representing the current UTC time.
|
||||||
|
"""
|
||||||
return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
||||||
|
|
||||||
|
|
||||||
def classify_exception(exc: BaseException) -> tuple[str, bool]:
|
def classify_exception(exc: BaseException) -> tuple[str, bool]:
|
||||||
|
"""Classify an exception into a probe error kind and retryability.
|
||||||
|
|
||||||
|
Maps exceptions to one of the standard error kinds defined in models.py
|
||||||
|
and determines whether the operation should be retried.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
exc: The exception to classify.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A tuple of (kind, retryable) where kind is one of the ERROR_KINDS
|
||||||
|
values and retryable indicates whether the operation might succeed
|
||||||
|
if retried.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
>>> classify_exception(asyncio.TimeoutError())
|
||||||
|
('timeout', True)
|
||||||
|
>>> classify_exception(PermissionError())
|
||||||
|
('no_privilege', False)
|
||||||
|
"""
|
||||||
if isinstance(exc, (asyncio.TimeoutError, TimeoutError, httpx.TimeoutException)):
|
if isinstance(exc, (asyncio.TimeoutError, TimeoutError, httpx.TimeoutException)):
|
||||||
return "timeout", True
|
return "timeout", True
|
||||||
if isinstance(exc, httpx.HTTPStatusError):
|
if isinstance(exc, httpx.HTTPStatusError):
|
||||||
|
|
@ -45,6 +69,25 @@ async def run_module(
|
||||||
timeout: float,
|
timeout: float,
|
||||||
source: str | None = None,
|
source: str | None = None,
|
||||||
) -> ModuleResult:
|
) -> ModuleResult:
|
||||||
|
"""Execute a probe module with timeout and error handling.
|
||||||
|
|
||||||
|
Runs the given coroutine with a timeout, catching any exceptions and
|
||||||
|
converting them into structured ProbeError objects. Tracks execution
|
||||||
|
timing and ensures the result has consistent metadata.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: The module name for identification in results.
|
||||||
|
coro: The coroutine to execute (typically an async probe function).
|
||||||
|
timeout: Maximum time in seconds to wait for the coroutine.
|
||||||
|
source: Optional source identifier for errors; defaults to name.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A ModuleResult with status 'ok', 'partial', or 'failed', containing
|
||||||
|
either the probe data or structured error information.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
asyncio.CancelledError: Propagated without modification.
|
||||||
|
"""
|
||||||
started_at = utc_now_iso()
|
started_at = utc_now_iso()
|
||||||
began = time.perf_counter()
|
began = time.perf_counter()
|
||||||
try:
|
try:
|
||||||
|
|
@ -71,6 +114,22 @@ async def run_module(
|
||||||
|
|
||||||
|
|
||||||
async def gather_modules(*results: Awaitable[ModuleResult]) -> list[ModuleResult]:
|
async def gather_modules(*results: Awaitable[ModuleResult]) -> list[ModuleResult]:
|
||||||
|
"""Run multiple modules concurrently and collect their results.
|
||||||
|
|
||||||
|
Executes all provided coroutines in parallel using asyncio.gather,
|
||||||
|
converting any exceptions into failed ModuleResult objects so that
|
||||||
|
one failing module doesn't prevent others from completing.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
*results: Variable number of awaitable ModuleResult coroutines.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A list of ModuleResult objects, one for each input coroutine.
|
||||||
|
Failed coroutines are represented as ModuleResult with status 'failed'.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
asyncio.CancelledError: Propagated without modification.
|
||||||
|
"""
|
||||||
gathered = await asyncio.gather(*results, return_exceptions=True)
|
gathered = await asyncio.gather(*results, return_exceptions=True)
|
||||||
out: list[ModuleResult] = []
|
out: list[ModuleResult] = []
|
||||||
for item in gathered:
|
for item in gathered:
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue