Add ResultReport hook
This commit is contained in:
parent
7b74b98168
commit
ebcd4b43c6
|
@ -6,8 +6,6 @@ from typing import Any
|
||||||
from pydantic import BaseModel, ConfigDict, Field
|
from pydantic import BaseModel, ConfigDict, Field
|
||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
|
|
||||||
console = Console(color_system="auto")
|
|
||||||
|
|
||||||
|
|
||||||
class ExecutionContext(BaseModel):
|
class ExecutionContext(BaseModel):
|
||||||
name: str
|
name: str
|
||||||
|
@ -23,6 +21,7 @@ class ExecutionContext(BaseModel):
|
||||||
end_wall: datetime | None = None
|
end_wall: datetime | None = None
|
||||||
|
|
||||||
extra: dict[str, Any] = Field(default_factory=dict)
|
extra: dict[str, Any] = Field(default_factory=dict)
|
||||||
|
console: Console = Field(default_factory=lambda: Console(color_system="auto"))
|
||||||
|
|
||||||
model_config = ConfigDict(arbitrary_types_allowed=True)
|
model_config = ConfigDict(arbitrary_types_allowed=True)
|
||||||
|
|
||||||
|
@ -75,7 +74,7 @@ class ExecutionContext(BaseModel):
|
||||||
message.append(f"❌ Exception: {summary['exception']}")
|
message.append(f"❌ Exception: {summary['exception']}")
|
||||||
else:
|
else:
|
||||||
message.append(f"✅ Result: {summary['result']}")
|
message.append(f"✅ Result: {summary['result']}")
|
||||||
(logger or console.print)("".join(message))
|
(logger or self.console.print)("".join(message))
|
||||||
|
|
||||||
def to_log_line(self) -> str:
|
def to_log_line(self) -> str:
|
||||||
"""Structured flat-line format for logging and metrics."""
|
"""Structured flat-line format for logging and metrics."""
|
||||||
|
|
|
@ -791,11 +791,10 @@ class Falyx:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
self._set_retry_policy(command)
|
self._set_retry_policy(command)
|
||||||
try:
|
try:
|
||||||
result = await self.headless(self.cli_args.name)
|
await self.headless(self.cli_args.name)
|
||||||
except FalyxError as error:
|
except FalyxError as error:
|
||||||
self.console.print(f"[{OneColors.DARK_RED}]❌ Error: {error}[/]")
|
self.console.print(f"[{OneColors.DARK_RED}]❌ Error: {error}[/]")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
self.console.print(f"[{OneColors.GREEN}]✅ Result:[/] {result}")
|
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
if self.cli_args.command == "run-all":
|
if self.cli_args.command == "run-all":
|
||||||
|
@ -807,7 +806,7 @@ class Falyx:
|
||||||
self.console.print(f"[{OneColors.LIGHT_YELLOW}]⚠️ No commands found with tag: '{self.cli_args.tag}'[/]")
|
self.console.print(f"[{OneColors.LIGHT_YELLOW}]⚠️ No commands found with tag: '{self.cli_args.tag}'[/]")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
self.console.print(f"[bold cyan]🚀 Running all commands with tag:[/] {self.cli_args.tag}")
|
self.console.print(f"[{OneColors.CYAN_b}]🚀 Running all commands with tag:[/] {self.cli_args.tag}")
|
||||||
for cmd in matching:
|
for cmd in matching:
|
||||||
self._set_retry_policy(cmd)
|
self._set_retry_policy(cmd)
|
||||||
await self.headless(cmd.key)
|
await self.headless(cmd.key)
|
||||||
|
|
|
@ -3,9 +3,29 @@ import time
|
||||||
|
|
||||||
from falyx.context import ExecutionContext
|
from falyx.context import ExecutionContext
|
||||||
from falyx.exceptions import CircuitBreakerOpen
|
from falyx.exceptions import CircuitBreakerOpen
|
||||||
|
from falyx.themes.colors import OneColors
|
||||||
from falyx.utils import logger
|
from falyx.utils import logger
|
||||||
|
|
||||||
|
|
||||||
|
class ResultReporter:
|
||||||
|
def __init__(self, formatter: callable = None):
|
||||||
|
"""
|
||||||
|
Optional result formatter. If not provided, uses repr(result).
|
||||||
|
"""
|
||||||
|
self.formatter = formatter or (lambda r: repr(r))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def __name__(self):
|
||||||
|
return "ResultReporter"
|
||||||
|
|
||||||
|
async def report(self, context: ExecutionContext):
|
||||||
|
if context.result is not None:
|
||||||
|
result_text = self.formatter(context.result)
|
||||||
|
duration = f"{context.duration:.3f}s" if context.duration is not None else "n/a"
|
||||||
|
context.console.print(f"[{OneColors.GREEN}]✅ '{context.name}' "
|
||||||
|
f"completed:[/] {result_text} in {duration}.")
|
||||||
|
|
||||||
|
|
||||||
class CircuitBreaker:
|
class CircuitBreaker:
|
||||||
def __init__(self, max_failures=3, reset_timeout=10):
|
def __init__(self, max_failures=3, reset_timeout=10):
|
||||||
self.max_failures = max_failures
|
self.max_failures = max_failures
|
||||||
|
@ -41,4 +61,3 @@ class CircuitBreaker:
|
||||||
self.failures = 0
|
self.failures = 0
|
||||||
self.open_until = None
|
self.open_until = None
|
||||||
logger.info("🔄 Circuit reset.")
|
logger.info("🔄 Circuit reset.")
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "falyx"
|
name = "falyx"
|
||||||
version = "0.1.2"
|
version = "0.1.4"
|
||||||
description = "Reliable and introspectable async CLI action framework."
|
description = "Reliable and introspectable async CLI action framework."
|
||||||
authors = ["Roland Thomas Jr <roland@rtj.dev>"]
|
authors = ["Roland Thomas Jr <roland@rtj.dev>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
Loading…
Reference in New Issue