```python:inference/core/workflows/core_steps/analytics/detection_event_log/v1.py
import heapq
from typing import Dict

from inference.core.workflows.prototypes.block import WorkflowBlock

MAX_VIDEOS = 100  # Maximum number of video streams to track before evicting oldest


class DetectionEventLogBlockV1(WorkflowBlock):

    def __init__(self):
        # Dict[video_id, Dict[tracker_id, DetectionEvent]]
        self._event_logs: Dict[str, Dict[int, DetectionEvent]] = {}
        # Dict[video_id, last_flush_frame]
        self._last_flush_frame: Dict[str, int] = {}
        # Dict[video_id, frame_count] - internal frame counter (increments each run)
        self._frame_count: Dict[str, int] = {}
        # Dict[video_id, last_access_frame] - tracks when each video was last accessed (global frame count)
        self._last_access: Dict[str, int] = {}
        # Global frame counter for tracking video access order
        # Min-heap of (last_access_frame, video_id) for efficient eviction
        self._access_heap: list = []
        # Global frame counter for tracking video access order
        self._global_frame: int = 0

    def _evict_oldest_video(self) -> None:
        """Remove the oldest video stream data when MAX_VIDEOS is exceeded."""
        if len(self._event_logs) <= MAX_VIDEOS:
            return

        # Pop from heap until we find a valid video (handles stale entries)
        while self._access_heap:
            _, oldest_video_id = heapq.heappop(self._access_heap)
            
            # Check if this video still exists (heap may contain stale entries)
            if oldest_video_id in self._event_logs:
                # Remove all data for this video
                del self._event_logs[oldest_video_id]
                del self._last_flush_frame[oldest_video_id]
                del self._frame_count[oldest_video_id]
                del self._last_access[oldest_video_id]
                break
```