util: add NetworkRetryManager, a baseclass for LNWorker and Network
This commit is contained in:
@@ -23,7 +23,8 @@
|
||||
import binascii
|
||||
import os, sys, re, json
|
||||
from collections import defaultdict, OrderedDict
|
||||
from typing import NamedTuple, Union, TYPE_CHECKING, Tuple, Optional, Callable, Any, Sequence
|
||||
from typing import (NamedTuple, Union, TYPE_CHECKING, Tuple, Optional, Callable, Any,
|
||||
Sequence, Dict, Generic, TypeVar)
|
||||
from datetime import datetime
|
||||
import decimal
|
||||
from decimal import Decimal
|
||||
@@ -1342,3 +1343,53 @@ callback_mgr = CallbackManager()
|
||||
trigger_callback = callback_mgr.trigger_callback
|
||||
register_callback = callback_mgr.register_callback
|
||||
unregister_callback = callback_mgr.unregister_callback
|
||||
|
||||
|
||||
_NetAddrType = TypeVar("_NetAddrType")
|
||||
|
||||
|
||||
class NetworkRetryManager(Generic[_NetAddrType]):
|
||||
"""Truncated Exponential Backoff for network connections."""
|
||||
|
||||
def __init__(
|
||||
self, *,
|
||||
max_retry_delay_normal: float,
|
||||
init_retry_delay_normal: float,
|
||||
max_retry_delay_urgent: float = None,
|
||||
init_retry_delay_urgent: float = None,
|
||||
):
|
||||
self._last_tried_addr = {} # type: Dict[_NetAddrType, Tuple[float, int]] # (unix ts, num_attempts)
|
||||
|
||||
# note: these all use "seconds" as unit
|
||||
if max_retry_delay_urgent is None:
|
||||
max_retry_delay_urgent = max_retry_delay_normal
|
||||
if init_retry_delay_urgent is None:
|
||||
init_retry_delay_urgent = init_retry_delay_normal
|
||||
self._max_retry_delay_normal = max_retry_delay_normal
|
||||
self._init_retry_delay_normal = init_retry_delay_normal
|
||||
self._max_retry_delay_urgent = max_retry_delay_urgent
|
||||
self._init_retry_delay_urgent = init_retry_delay_urgent
|
||||
|
||||
def _trying_addr_now(self, addr: _NetAddrType) -> None:
|
||||
last_time, num_attempts = self._last_tried_addr.get(addr, (0, 0))
|
||||
self._last_tried_addr[addr] = time.time(), num_attempts + 1
|
||||
|
||||
def _on_connection_successfully_established(self, addr: _NetAddrType) -> None:
|
||||
self._last_tried_addr[addr] = time.time(), 0
|
||||
|
||||
def _can_retry_addr(self, peer: _NetAddrType, *,
|
||||
now: float = None, urgent: bool = False) -> bool:
|
||||
if now is None:
|
||||
now = time.time()
|
||||
last_time, num_attempts = self._last_tried_addr.get(peer, (0, 0))
|
||||
if urgent:
|
||||
delay = min(self._max_retry_delay_urgent,
|
||||
self._init_retry_delay_urgent * 2 ** num_attempts)
|
||||
else:
|
||||
delay = min(self._max_retry_delay_normal,
|
||||
self._init_retry_delay_normal * 2 ** num_attempts)
|
||||
next_time = last_time + delay
|
||||
return next_time < now
|
||||
|
||||
def _clear_addr_retry_times(self) -> None:
|
||||
self._last_tried_addr.clear()
|
||||
|
||||
Reference in New Issue
Block a user