""" Event models for Information Spaces. This module defines the event types and data structures used by the event system for space operations. """ from dataclasses import dataclass, field from datetime import datetime from enum import Enum from typing import Any, Dict, Optional import uuid class SpaceEventType(Enum): """ Types of events that can occur in the space system. Events are organized by category: - Space lifecycle: creation, updates, deletion, status changes - Document operations: add, update, remove, move - Variable operations: set, delete - Rendering: start, complete, fail - Sync: start, complete, conflict """ # Space lifecycle events SPACE_CREATED = "space.created" SPACE_UPDATED = "space.updated" SPACE_DELETED = "space.deleted" SPACE_ACTIVATED = "space.activated" SPACE_ARCHIVED = "space.archived" # Document events DOCUMENT_ADDED = "document.added" DOCUMENT_UPDATED = "document.updated" DOCUMENT_REMOVED = "document.removed" DOCUMENT_MOVED = "document.moved" DOCUMENT_CONTENT_CHANGED = "document.content_changed" # Variable events VARIABLE_SET = "variable.set" VARIABLE_DELETED = "variable.deleted" # Reference events REFERENCE_ADDED = "reference.added" REFERENCE_CLEARED = "reference.cleared" # Rendering events RENDER_STARTED = "render.started" RENDER_COMPLETED = "render.completed" RENDER_FAILED = "render.failed" # Sync events SYNC_STARTED = "sync.started" SYNC_COMPLETED = "sync.completed" SYNC_CONFLICT = "sync.conflict" # Cache events CACHE_INVALIDATED = "cache.invalidated" @dataclass class SpaceEvent: """ Represents an event in the space system. Events are immutable records of operations that have occurred. They carry enough information for handlers to react appropriately. Attributes: event_type: The type of event space_id: The ID of the affected space payload: Event-specific data event_id: Unique identifier for this event timestamp: When the event occurred source: Optional identifier of the event source correlation_id: Optional ID to correlate related events """ event_type: SpaceEventType space_id: str payload: Dict[str, Any] = field(default_factory=dict) event_id: str = field(default_factory=lambda: str(uuid.uuid4())) timestamp: datetime = field(default_factory=datetime.now) source: Optional[str] = None correlation_id: Optional[str] = None def to_dict(self) -> Dict[str, Any]: """Convert the event to a dictionary for serialization.""" return { "event_id": self.event_id, "event_type": self.event_type.value, "space_id": self.space_id, "payload": self.payload, "timestamp": self.timestamp.isoformat(), "source": self.source, "correlation_id": self.correlation_id, } @classmethod def from_dict(cls, data: Dict[str, Any]) -> "SpaceEvent": """Create an event from a dictionary.""" return cls( event_id=data.get("event_id", str(uuid.uuid4())), event_type=SpaceEventType(data["event_type"]), space_id=data["space_id"], payload=data.get("payload", {}), timestamp=datetime.fromisoformat(data["timestamp"]) if data.get("timestamp") else datetime.now(), source=data.get("source"), correlation_id=data.get("correlation_id"), ) # Convenience factory functions for common events def space_created_event( space_id: str, name: str, source: Optional[str] = None, ) -> SpaceEvent: """Create a SPACE_CREATED event.""" return SpaceEvent( event_type=SpaceEventType.SPACE_CREATED, space_id=space_id, payload={"name": name}, source=source, ) def space_updated_event( space_id: str, changes: Dict[str, Any], source: Optional[str] = None, ) -> SpaceEvent: """Create a SPACE_UPDATED event.""" return SpaceEvent( event_type=SpaceEventType.SPACE_UPDATED, space_id=space_id, payload={"changes": changes}, source=source, ) def space_deleted_event( space_id: str, name: str, source: Optional[str] = None, ) -> SpaceEvent: """Create a SPACE_DELETED event.""" return SpaceEvent( event_type=SpaceEventType.SPACE_DELETED, space_id=space_id, payload={"name": name}, source=source, ) def document_added_event( space_id: str, document_id: str, space_path: str, source: Optional[str] = None, ) -> SpaceEvent: """Create a DOCUMENT_ADDED event.""" return SpaceEvent( event_type=SpaceEventType.DOCUMENT_ADDED, space_id=space_id, payload={"document_id": document_id, "space_path": space_path}, source=source, ) def document_updated_event( space_id: str, document_id: str, changes: Dict[str, Any], source: Optional[str] = None, ) -> SpaceEvent: """Create a DOCUMENT_UPDATED event.""" return SpaceEvent( event_type=SpaceEventType.DOCUMENT_UPDATED, space_id=space_id, payload={"document_id": document_id, "changes": changes}, source=source, ) def document_removed_event( space_id: str, document_id: str, space_path: str, source: Optional[str] = None, ) -> SpaceEvent: """Create a DOCUMENT_REMOVED event.""" return SpaceEvent( event_type=SpaceEventType.DOCUMENT_REMOVED, space_id=space_id, payload={"document_id": document_id, "space_path": space_path}, source=source, ) def document_content_changed_event( space_id: str, document_id: str, old_hash: Optional[str], new_hash: str, source: Optional[str] = None, ) -> SpaceEvent: """Create a DOCUMENT_CONTENT_CHANGED event.""" return SpaceEvent( event_type=SpaceEventType.DOCUMENT_CONTENT_CHANGED, space_id=space_id, payload={ "document_id": document_id, "old_hash": old_hash, "new_hash": new_hash, }, source=source, ) def cache_invalidated_event( space_id: str, document_ids: list, reason: str, source: Optional[str] = None, ) -> SpaceEvent: """Create a CACHE_INVALIDATED event.""" return SpaceEvent( event_type=SpaceEventType.CACHE_INVALIDATED, space_id=space_id, payload={"document_ids": document_ids, "reason": reason}, source=source, )