Skip to content

Commit

Permalink
refactor(engine): Rename RegistryActionErrorInfo to ExecutorActionErr…
Browse files Browse the repository at this point in the history
…orInfo (#689)
  • Loading branch information
daryllimyt authored Jan 2, 2025
1 parent f5ee456 commit 5fffb7b
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 46 deletions.
4 changes: 2 additions & 2 deletions tests/unit/test_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
from tracecat.contexts import RunContext
from tracecat.dsl.common import create_default_execution_context
from tracecat.dsl.models import ActionStatement, RunActionInput
from tracecat.executor.models import ExecutorActionErrorInfo
from tracecat.executor.service import run_action_from_input, sync_executor_entrypoint
from tracecat.expressions.expectations import ExpectedField
from tracecat.logger import logger
from tracecat.registry.actions.models import (
ActionStep,
RegistryActionCreate,
RegistryActionErrorInfo,
TemplateAction,
TemplateActionDefinition,
)
Expand Down Expand Up @@ -297,7 +297,7 @@ def test_sync_executor_entrypoint_returns_wrapped_error(

# Run the entrypoint and verify it returns a RegistryActionErrorInfo
result = sync_executor_entrypoint(input, test_role)
assert isinstance(result, RegistryActionErrorInfo)
assert isinstance(result, ExecutorActionErrorInfo)
assert result.type == "ValueError"
assert result.message == "__EXPECTED_MESSAGE__"
assert result.action_name == "test.error_action"
Expand Down
5 changes: 2 additions & 3 deletions tracecat/executor/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@
from tracecat.clients import AuthenticatedServiceClient
from tracecat.contexts import ctx_role
from tracecat.dsl.models import RunActionInput
from tracecat.executor.models import ExecutorSyncInput
from tracecat.executor.models import ExecutorActionErrorInfo, ExecutorSyncInput
from tracecat.logger import logger
from tracecat.registry.actions.models import (
RegistryActionErrorInfo,
RegistryActionValidateResponse,
)
from tracecat.types.auth import Role
Expand Down Expand Up @@ -192,7 +191,7 @@ def _handle_http_status_error(
and (detail := resp.get("detail"))
and isinstance(detail, Mapping)
):
val_detail = RegistryActionErrorInfo(**detail)
val_detail = ExecutorActionErrorInfo(**detail)
detail = str(val_detail)
else:
detail = e.response.text
Expand Down
48 changes: 48 additions & 0 deletions tracecat/executor/models.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,53 @@
from __future__ import annotations

import traceback

from pydantic import UUID4, BaseModel


class ExecutorSyncInput(BaseModel):
repository_id: UUID4


class ExecutorActionErrorInfo(BaseModel):
"""An error that occurred in the registry."""

action_name: str
"""Name of the action that failed."""

type: str
"""Type of the error."""

message: str
"""Error message."""

filename: str
"""File where the error occurred."""

function: str
"""Function where the error occurred."""

lineno: int | None = None
"""Line number where the error occurred."""

def __str__(self) -> str:
return (
f"{self.type}: {self.message}"
f"\n\n{'-'*30}"
f"\nFile: {self.filename}"
f"\nFunction: {self.function}"
f"\nLine: {self.lineno}"
)

@staticmethod
def from_exc(e: Exception, action_name: str) -> ExecutorActionErrorInfo:
"""Create an error info from an exception."""
tb = traceback.extract_tb(e.__traceback__)[-1] # Get the last frame
return ExecutorActionErrorInfo(
action_name=action_name,
type=e.__class__.__name__,
message=str(e),
filename=tb.filename,
function=tb.name,
lineno=tb.lineno,
)
5 changes: 2 additions & 3 deletions tracecat/executor/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@
from tracecat.contexts import ctx_logger, ctx_role
from tracecat.db.dependencies import AsyncDBSession
from tracecat.dsl.models import RunActionInput
from tracecat.executor.models import ExecutorSyncInput
from tracecat.executor.models import ExecutorActionErrorInfo, ExecutorSyncInput
from tracecat.executor.service import dispatch_action_on_cluster
from tracecat.logger import logger
from tracecat.registry.actions.models import (
RegistryActionErrorInfo,
RegistryActionValidate,
RegistryActionValidateResponse,
)
Expand Down Expand Up @@ -79,7 +78,7 @@ async def run_action(
detail=err_info_dict,
) from e
except Exception as e:
err_info = RegistryActionErrorInfo.from_exc(e, action_name)
err_info = ExecutorActionErrorInfo.from_exc(e, action_name)
err_info_dict = err_info.model_dump(mode="json")
act_logger.error("Error running action", **err_info_dict)
raise HTTPException(
Expand Down
8 changes: 4 additions & 4 deletions tracecat/executor/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
RunActionInput,
)
from tracecat.executor.engine import EXECUTION_TIMEOUT
from tracecat.executor.models import ExecutorActionErrorInfo
from tracecat.expressions.common import ExprContext, ExprOperand
from tracecat.expressions.eval import (
eval_templated_object,
Expand All @@ -37,7 +38,6 @@
from tracecat.parse import traverse_leaves
from tracecat.registry.actions.models import (
BoundRegistryAction,
RegistryActionErrorInfo,
)
from tracecat.registry.actions.service import RegistryActionsService
from tracecat.secrets.common import apply_masks_object
Expand All @@ -50,7 +50,7 @@


type ArgsT = Mapping[str, Any]
type ExecutionResult = Any | RegistryActionErrorInfo
type ExecutionResult = Any | ExecutorActionErrorInfo


def sync_executor_entrypoint(input: RunActionInput, role: Role) -> ExecutionResult:
Expand All @@ -74,7 +74,7 @@ def sync_executor_entrypoint(input: RunActionInput, role: Role) -> ExecutionResu
type=type(e).__name__,
traceback=traceback.format_exc(),
)
return RegistryActionErrorInfo.from_exc(e, input.task.action)
return ExecutorActionErrorInfo.from_exc(e, input.task.action)
finally:
loop.run_until_complete(async_engine.dispose())
loop.close() # We always close the loop
Expand Down Expand Up @@ -343,7 +343,7 @@ async def run_action_on_ray_cluster(

# Here, we have some result or error.
# Reconstruct the error and raise some kind of proxy
if isinstance(exec_result, RegistryActionErrorInfo):
if isinstance(exec_result, ExecutorActionErrorInfo):
logger.info("Raising executor error proxy")
raise WrappedExecutionError(error=exec_result)
return exec_result
Expand Down
34 changes: 0 additions & 34 deletions tracecat/registry/actions/models.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from __future__ import annotations

import inspect
import traceback
from collections.abc import Callable, Mapping
from pathlib import Path
from typing import Annotated, Any, Literal, TypedDict, TypeVar, cast
Expand Down Expand Up @@ -489,36 +488,3 @@ def db_to_interface(action: RegistryAction) -> RegistryActionInterface:
f"Unknown implementation type: {action.implementation}"
)
return intf


class RegistryActionErrorInfo(BaseModel):
"""An error that occurred in the registry."""

action_name: str
type: str
message: str
filename: str
function: str
lineno: int | None = None

def __str__(self) -> str:
return (
f"{self.type}: {self.message}"
f"\n\n{'-'*30}"
f"\nFile: {self.filename}"
f"\nFunction: {self.function}"
f"\nLine: {self.lineno}"
)

@staticmethod
def from_exc(e: Exception, action_name: str) -> RegistryActionErrorInfo:
"""Create an error info from an exception."""
tb = traceback.extract_tb(e.__traceback__)[-1] # Get the last frame
return RegistryActionErrorInfo(
action_name=action_name,
type=e.__class__.__name__,
message=str(e),
filename=tb.filename,
function=tb.name,
lineno=tb.lineno,
)

0 comments on commit 5fffb7b

Please sign in to comment.