Voice et bot modif
This commit is contained in:
parent
189d56026b
commit
7333a22bcd
10774 changed files with 634644 additions and 933308 deletions
|
|
@ -0,0 +1,102 @@
|
|||
import math
|
||||
import threading
|
||||
from abc import ABC, abstractmethod
|
||||
from datetime import datetime, timedelta
|
||||
from typing import List, Optional, Type
|
||||
|
||||
from redis.multidb.circuit import State as CBState
|
||||
|
||||
DEFAULT_MIN_NUM_FAILURES = 1000
|
||||
DEFAULT_FAILURE_RATE_THRESHOLD = 0.1
|
||||
DEFAULT_FAILURES_DETECTION_WINDOW = 2
|
||||
|
||||
|
||||
class FailureDetector(ABC):
|
||||
@abstractmethod
|
||||
def register_failure(self, exception: Exception, cmd: tuple) -> None:
|
||||
"""Register a failure that occurred during command execution."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def register_command_execution(self, cmd: tuple) -> None:
|
||||
"""Register a command execution."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def set_command_executor(self, command_executor) -> None:
|
||||
"""Set the command executor for this failure."""
|
||||
pass
|
||||
|
||||
|
||||
class CommandFailureDetector(FailureDetector):
|
||||
"""
|
||||
Detects a failure based on a threshold of failed commands during a specific period of time.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
min_num_failures: int = DEFAULT_MIN_NUM_FAILURES,
|
||||
failure_rate_threshold: float = DEFAULT_FAILURE_RATE_THRESHOLD,
|
||||
failure_detection_window: float = DEFAULT_FAILURES_DETECTION_WINDOW,
|
||||
error_types: Optional[List[Type[Exception]]] = None,
|
||||
) -> None:
|
||||
"""
|
||||
Initialize a new CommandFailureDetector instance.
|
||||
|
||||
Args:
|
||||
min_num_failures: Minimal count of failures required for failover
|
||||
failure_rate_threshold: Percentage of failures required for failover
|
||||
failure_detection_window: Time interval for executing health checks.
|
||||
error_types: Optional list of exception types to trigger failover. If None, all exceptions are counted.
|
||||
|
||||
The detector tracks command failures within a sliding time window. When the number of failures
|
||||
exceeds the threshold within the specified duration, it triggers failure detection.
|
||||
"""
|
||||
self._command_executor = None
|
||||
self._min_num_failures = min_num_failures
|
||||
self._failure_rate_threshold = failure_rate_threshold
|
||||
self._failure_detection_window = failure_detection_window
|
||||
self._error_types = error_types
|
||||
self._commands_executed: int = 0
|
||||
self._start_time: datetime = datetime.now()
|
||||
self._end_time: datetime = self._start_time + timedelta(
|
||||
seconds=self._failure_detection_window
|
||||
)
|
||||
self._failures_count: int = 0
|
||||
self._lock = threading.RLock()
|
||||
|
||||
def register_failure(self, exception: Exception, cmd: tuple) -> None:
|
||||
with self._lock:
|
||||
if self._error_types:
|
||||
if type(exception) in self._error_types:
|
||||
self._failures_count += 1
|
||||
else:
|
||||
self._failures_count += 1
|
||||
|
||||
self._check_threshold()
|
||||
|
||||
def set_command_executor(self, command_executor) -> None:
|
||||
self._command_executor = command_executor
|
||||
|
||||
def register_command_execution(self, cmd: tuple) -> None:
|
||||
with self._lock:
|
||||
if not self._start_time < datetime.now() < self._end_time:
|
||||
self._reset()
|
||||
|
||||
self._commands_executed += 1
|
||||
|
||||
def _check_threshold(self):
|
||||
if self._failures_count >= self._min_num_failures and self._failures_count >= (
|
||||
math.ceil(self._commands_executed * self._failure_rate_threshold)
|
||||
):
|
||||
self._command_executor.active_database.circuit.state = CBState.OPEN
|
||||
self._reset()
|
||||
|
||||
def _reset(self) -> None:
|
||||
with self._lock:
|
||||
self._start_time = datetime.now()
|
||||
self._end_time = self._start_time + timedelta(
|
||||
seconds=self._failure_detection_window
|
||||
)
|
||||
self._failures_count = 0
|
||||
self._commands_executed = 0
|
||||
Loading…
Add table
Add a link
Reference in a new issue