---
title: "Event Handlers"
description: "Implementing event handlers in TraceRTM"
keywords: [event handlers, events, subscribers, listeners]
---

# Event Handlers

How to implement and register event handlers in TraceRTM.

## Handler Registration

### Decorator Pattern

```python
from tracertm.events import event_bus

@event_bus.subscribe("item.created")
async def on_item_created(event: dict):
    """Handle item creation."""
    item_id = event["item_id"]
    # Handler logic
    pass
```

### Manual Registration

```python
def handle_item_updated(event: dict):
    """Handle item update."""
    pass

event_bus.subscribe("item.updated", handle_item_updated)
```

## Handler Types

### Synchronous Handlers

```python
@event_bus.subscribe("item.created")
def on_item_created(event: dict):
    """Synchronous handler."""
    # Quick operations
    cache.set(f"item:{event['item_id']}", event)
```

### Asynchronous Handlers

```python
@event_bus.subscribe("item.created")
async def on_item_created(event: dict):
    """Asynchronous handler."""
    # I/O operations
    await notification_service.send(event["item_id"])
    await search_service.index_item(event["item_id"])
```

## Handler Examples

### Notification Handler

```python
@event_bus.subscribe("item.created")
async def notify_item_created(event: dict):
    """Send notification on item creation."""
    item_id = event["item_id"]
    project_id = event["project_id"]
    
    # Get project subscribers
    subscribers = await get_project_subscribers(project_id)
    
    # Send notifications
    for subscriber in subscribers:
        await email_service.send(
            to=subscriber.email,
            subject=f"New item: {event['title']}",
            body=f"Item {item_id} was created"
        )
```

### Cache Invalidation Handler

```python
@event_bus.subscribe("item.updated")
async def invalidate_cache(event: dict):
    """Invalidate cache on item update."""
    item_id = event["item_id"]
    
    # Invalidate item cache
    await cache.delete(f"item:{item_id}")
    
    # Invalidate related caches
    await cache.delete(f"items:project:{event['project_id']}")
```

### Search Index Handler

```python
@event_bus.subscribe("item.created")
@event_bus.subscribe("item.updated")
async def update_search_index(event: dict):
    """Update search index."""
    item_id = event["item_id"]
    item = await item_repo.get_by_id(item_id)
    
    # Index item
    await search_service.index({
        "id": item.id,
        "title": item.title,
        "description": item.description,
        "view": item.view
    })
```

## Error Handling

### Try-Except in Handlers

```python
@event_bus.subscribe("item.created")
async def handle_item_created(event: dict):
    """Handle with error handling."""
    try:
        # Handler logic
        await process_item(event)
    except Exception as e:
        logger.error(f"Error in item.created handler: {e}", exc_info=True)
        # Don't re-raise - allow other handlers to process
```

### Error Handler Middleware

```python
class ErrorHandlingMiddleware:
    async def wrap(self, handler: Callable, event: dict):
        try:
            return await handler(event)
        except Exception as e:
            logger.error(f"Handler error: {e}", exc_info=True)
            # Optionally send to error tracking service
            await error_tracker.record(e, {"event": event})
```

## Handler Ordering

### Priority Handlers

```python
# High priority - runs first
@event_bus.subscribe("item.created", priority=1)
async def validate_item(event: dict):
    """Validate item (high priority)."""
    pass

# Low priority - runs last
@event_bus.subscribe("item.created", priority=10)
async def log_item(event: dict):
    """Log item creation (low priority)."""
    pass
```

## Testing Handlers

### Mock Event Bus

```python
import pytest
from unittest.mock import Mock

@pytest.fixture
def mock_event_bus():
    return Mock()

def test_item_creation_publishes_event(mock_event_bus):
    """Test that item creation publishes event."""
    service = ItemService(event_bus=mock_event_bus)
    service.create({"title": "Test"})
    
    mock_event_bus.publish.assert_called_once_with(
        "item.created",
        {"title": "Test"}
    )
```

## Related Documentation

- [Event System](./05-event-system) - Event system overview
- [Webhooks API](/docs/api-reference/rest-api/webhooks) - Webhook integration
