suna/backend/triggers/repositories/interfaces.py

316 lines
7.7 KiB
Python

"""
Repository Interfaces for the Triggers Domain
These interfaces define the contracts for data access operations.
They follow the Repository pattern to abstract data persistence concerns
from the domain logic.
"""
from abc import ABC, abstractmethod
from typing import List, Optional, Dict, Any
from datetime import datetime
from ..domain.entities import Trigger, TriggerEvent, TriggerResult
from ..domain.value_objects import TriggerIdentity
class TriggerRepository(ABC):
"""
Abstract repository for trigger data persistence
This interface defines the contract for storing and retrieving
trigger configuration data.
"""
@abstractmethod
async def save(self, trigger: Trigger) -> None:
"""
Save a trigger to the repository
Args:
trigger: The trigger to save
Raises:
RepositoryError: If the save operation fails
"""
pass
@abstractmethod
async def find_by_id(self, trigger_id: str) -> Optional[Trigger]:
"""
Find a trigger by its ID
Args:
trigger_id: The trigger ID to search for
Returns:
The trigger if found, None otherwise
Raises:
RepositoryError: If the query fails
"""
pass
@abstractmethod
async def find_by_agent_id(self, agent_id: str) -> List[Trigger]:
"""
Find all triggers for a specific agent
Args:
agent_id: The agent ID to search for
Returns:
List of triggers for the agent
Raises:
RepositoryError: If the query fails
"""
pass
@abstractmethod
async def find_active_triggers(self) -> List[Trigger]:
"""
Find all active triggers
Returns:
List of active triggers
Raises:
RepositoryError: If the query fails
"""
pass
@abstractmethod
async def find_by_provider_id(self, provider_id: str) -> List[Trigger]:
"""
Find all triggers using a specific provider
Args:
provider_id: The provider ID to search for
Returns:
List of triggers using the provider
Raises:
RepositoryError: If the query fails
"""
pass
@abstractmethod
async def update(self, trigger: Trigger) -> None:
"""
Update an existing trigger
Args:
trigger: The trigger to update
Raises:
RepositoryError: If the update operation fails
NotFoundError: If the trigger doesn't exist
"""
pass
@abstractmethod
async def delete(self, trigger_id: str) -> bool:
"""
Delete a trigger by ID
Args:
trigger_id: The trigger ID to delete
Returns:
True if the trigger was deleted, False if not found
Raises:
RepositoryError: If the delete operation fails
"""
pass
@abstractmethod
async def exists(self, trigger_id: str) -> bool:
"""
Check if a trigger exists
Args:
trigger_id: The trigger ID to check
Returns:
True if the trigger exists, False otherwise
Raises:
RepositoryError: If the query fails
"""
pass
@abstractmethod
async def count_by_agent_id(self, agent_id: str) -> int:
"""
Count triggers for a specific agent
Args:
agent_id: The agent ID to count for
Returns:
Number of triggers for the agent
Raises:
RepositoryError: If the query fails
"""
pass
class TriggerEventLogRepository(ABC):
"""
Abstract repository for trigger event logging
This interface defines the contract for storing and retrieving
trigger event execution logs.
"""
@abstractmethod
async def log_event(
self,
event: TriggerEvent,
result: TriggerResult,
execution_time_ms: Optional[int] = None
) -> str:
"""
Log a trigger event execution
Args:
event: The trigger event that was processed
result: The result of processing the event
execution_time_ms: Time taken to process the event in milliseconds
Returns:
The log entry ID
Raises:
RepositoryError: If the logging operation fails
"""
pass
@abstractmethod
async def find_logs_by_trigger_id(
self,
trigger_id: str,
limit: int = 100,
offset: int = 0
) -> List[Dict[str, Any]]:
"""
Find event logs for a specific trigger
Args:
trigger_id: The trigger ID to search for
limit: Maximum number of logs to return
offset: Number of logs to skip
Returns:
List of log entries
Raises:
RepositoryError: If the query fails
"""
pass
@abstractmethod
async def find_logs_by_agent_id(
self,
agent_id: str,
limit: int = 100,
offset: int = 0
) -> List[Dict[str, Any]]:
"""
Find event logs for a specific agent
Args:
agent_id: The agent ID to search for
limit: Maximum number of logs to return
offset: Number of logs to skip
Returns:
List of log entries
Raises:
RepositoryError: If the query fails
"""
pass
@abstractmethod
async def find_failed_events(
self,
since: Optional[datetime] = None,
limit: int = 100
) -> List[Dict[str, Any]]:
"""
Find failed trigger events
Args:
since: Only return events after this timestamp
limit: Maximum number of events to return
Returns:
List of failed event logs
Raises:
RepositoryError: If the query fails
"""
pass
@abstractmethod
async def get_execution_stats(
self,
trigger_id: str,
hours: int = 24
) -> Dict[str, Any]:
"""
Get execution statistics for a trigger
Args:
trigger_id: The trigger ID to get stats for
hours: Number of hours to look back
Returns:
Dictionary with execution statistics
Raises:
RepositoryError: If the query fails
"""
pass
@abstractmethod
async def cleanup_old_logs(self, days_to_keep: int = 30) -> int:
"""
Clean up old log entries
Args:
days_to_keep: Number of days of logs to keep
Returns:
Number of log entries deleted
Raises:
RepositoryError: If the cleanup operation fails
"""
pass
# Repository Exceptions
class RepositoryError(Exception):
"""Base exception for repository operations"""
pass
class NotFoundError(RepositoryError):
"""Exception raised when a requested entity is not found"""
pass
class DuplicateError(RepositoryError):
"""Exception raised when trying to create a duplicate entity"""
pass
class ValidationError(RepositoryError):
"""Exception raised when repository data validation fails"""
pass