76 lines
1.5 KiB
Python
76 lines
1.5 KiB
Python
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
|