import time from dataclasses import dataclass from typing import Any from core.domain.models import NormalizedCDR @dataclass(frozen=True, slots=True) class KafkaPosition: topic: str partition: int offset: int @dataclass(frozen=True, slots=True) class BufferedCDR: cdr: NormalizedCDR original_payload: dict[str, Any] position: KafkaPosition class MicroBatch: def __init__( self, max_size: int, flush_interval_seconds: float, ) -> None: self._max_size = max_size self._flush_interval_seconds = flush_interval_seconds self._items: list[BufferedCDR] = [] self._started_at: float | None = None def add( self, item: BufferedCDR, ) -> None: if not self._items: self._started_at = time.monotonic() self._items.append(item) @property def size(self) -> int: return len(self._items) @property def is_empty(self) -> bool: return not self._items @property def is_full(self) -> bool: return len(self._items) >= self._max_size def is_due(self) -> bool: if not self._items: return False if self._started_at is None: return False elapsed = ( time.monotonic() - self._started_at ) return elapsed >= self._flush_interval_seconds def snapshot(self) -> list[BufferedCDR]: return list(self._items) def clear(self) -> None: self._items.clear() self._started_at = None