from __future__ import annotations

import threading
from typing import Dict, Tuple


class Sampler:
    def __init__(self, sample_rate: int):
        if not isinstance(sample_rate, int) or sample_rate < 1:
            raise ValueError("sample_rate must be an integer >= 1")
        self._sample_rate = sample_rate
        self._counters: Dict[Tuple[str, str], int] = {}
        self._lock = threading.Lock()

    def should_sample(self, stream_id: str, signal: str) -> bool:
        if self._sample_rate <= 1:
            return True
        key = (str(stream_id), signal)
        with self._lock:
            counter = self._counters.get(key, 0)
            should_sample = (counter % self._sample_rate) == 0
            self._counters[key] = counter + 1
        return should_sample
