mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2024-11-10 19:46:36 +03:00
Fix a couple of inconsistencies in the public interface (#1102)
* Create `_NOT_A_REQUEST` when needed. Currently, modifications in the raised exception would be "global". * `retries` parameters were actually attempts. This has been fixed to actually be the amount of retries, so 0 now means don't retry. * Helper function to deal with retries instead of using a range with different styles every time.
This commit is contained in:
parent
c9e9b82eac
commit
c8f16a4e89
|
@ -53,7 +53,7 @@ class _TakeoutClient:
|
|||
wrapped = []
|
||||
for r in requests:
|
||||
if not isinstance(r, TLRequest):
|
||||
raise _NOT_A_REQUEST
|
||||
raise _NOT_A_REQUEST()
|
||||
await r.resolve(self, utils)
|
||||
wrapped.append(functions.InvokeWithTakeoutRequest(takeout_id, r))
|
||||
|
||||
|
|
|
@ -71,23 +71,23 @@ class TelegramBaseClient(abc.ABC):
|
|||
invoked requests, and you should use ``asyncio.wait`` or
|
||||
``asyncio.wait_for`` for that.
|
||||
|
||||
request_retries (`int`, optional):
|
||||
request_retries (`int` | `None`, optional):
|
||||
How many times a request should be retried. Request are retried
|
||||
when Telegram is having internal issues (due to either
|
||||
``errors.ServerError`` or ``errors.RpcCallFailError``),
|
||||
when there is a ``errors.FloodWaitError`` less than
|
||||
`flood_sleep_threshold`, or when there's a migrate error.
|
||||
|
||||
May set to a false-y value (``0`` or ``None``) for infinite
|
||||
retries, but this is not recommended, since some requests can
|
||||
always trigger a call fail (such as searching for messages).
|
||||
May take a negative or ``None`` value for infinite retries, but
|
||||
this is not recommended, since some requests can always trigger
|
||||
a call fail (such as searching for messages).
|
||||
|
||||
connection_retries (`int`, optional):
|
||||
connection_retries (`int` | `None`, optional):
|
||||
How many times the reconnection should retry, either on the
|
||||
initial connection or when Telegram disconnects us. May be
|
||||
set to a false-y value (``0`` or ``None``) for infinite
|
||||
retries, but this is not recommended, since the program can
|
||||
get stuck in an infinite loop.
|
||||
set to a negative or ``None`` value for infinite retries, but
|
||||
this is not recommended, since the program can get stuck in an
|
||||
infinite loop.
|
||||
|
||||
retry_delay (`int` | `float`, optional):
|
||||
The delay in seconds to sleep between automatic reconnections.
|
||||
|
@ -236,8 +236,8 @@ class TelegramBaseClient(abc.ABC):
|
|||
self.api_id = int(api_id)
|
||||
self.api_hash = api_hash
|
||||
|
||||
self._request_retries = request_retries or sys.maxsize
|
||||
self._connection_retries = connection_retries or sys.maxsize
|
||||
self._request_retries = request_retries
|
||||
self._connection_retries = connection_retries
|
||||
self._retry_delay = retry_delay or 0
|
||||
self._proxy = proxy
|
||||
self._timeout = timeout
|
||||
|
|
|
@ -6,8 +6,9 @@ from .telegrambaseclient import TelegramBaseClient
|
|||
from .. import errors, utils
|
||||
from ..errors import MultiError, RPCError
|
||||
from ..tl import TLObject, TLRequest, types, functions
|
||||
from ..helpers import retry_range
|
||||
|
||||
_NOT_A_REQUEST = TypeError('You can only invoke requests, not types!')
|
||||
_NOT_A_REQUEST = lambda: TypeError('You can only invoke requests, not types!')
|
||||
|
||||
|
||||
class UserMethods(TelegramBaseClient):
|
||||
|
@ -15,7 +16,7 @@ class UserMethods(TelegramBaseClient):
|
|||
requests = (request if utils.is_list_like(request) else (request,))
|
||||
for r in requests:
|
||||
if not isinstance(r, TLRequest):
|
||||
raise _NOT_A_REQUEST
|
||||
raise _NOT_A_REQUEST()
|
||||
await r.resolve(self, utils)
|
||||
|
||||
# Avoid making the request if it's already in a flood wait
|
||||
|
@ -34,7 +35,7 @@ class UserMethods(TelegramBaseClient):
|
|||
|
||||
request_index = 0
|
||||
self._last_request = time.time()
|
||||
for _ in range(self._request_retries):
|
||||
for attempt in retry_range(self._request_retries):
|
||||
try:
|
||||
future = self._sender.send(request, ordered=ordered)
|
||||
if isinstance(future, list):
|
||||
|
@ -86,7 +87,8 @@ class UserMethods(TelegramBaseClient):
|
|||
raise
|
||||
await self._switch_dc(e.new_dc)
|
||||
|
||||
raise ValueError('Number of retries reached 0')
|
||||
raise ValueError('Request was unsuccessful {} time(s)'
|
||||
.format(attempt))
|
||||
|
||||
# region Public methods
|
||||
|
||||
|
|
|
@ -72,6 +72,21 @@ def strip_text(text, entities):
|
|||
return text
|
||||
|
||||
|
||||
def retry_range(retries):
|
||||
"""
|
||||
Generates an integer sequence starting from 1. If `retries` is
|
||||
negative or ``None`` then sequence is infinite, otherwise it will
|
||||
end at `retries + 1`.
|
||||
"""
|
||||
yield 1
|
||||
if retries is None:
|
||||
retries = -1
|
||||
attempt = 0
|
||||
while attempt != retries:
|
||||
attempt += 1
|
||||
yield 1 + attempt
|
||||
|
||||
|
||||
# endregion
|
||||
|
||||
# region Cryptographic related utils
|
||||
|
|
|
@ -22,6 +22,7 @@ from ..tl.types import (
|
|||
MsgsStateInfo, MsgsAllInfo, MsgResendReq, upload
|
||||
)
|
||||
from ..crypto import AuthKey
|
||||
from ..helpers import retry_range
|
||||
|
||||
|
||||
def _cancellable(func):
|
||||
|
@ -211,26 +212,27 @@ class MTProtoSender:
|
|||
receive loops.
|
||||
"""
|
||||
self._log.info('Connecting to %s...', self._connection)
|
||||
for retry in range(1, self._retries + 1):
|
||||
for attempt in retry_range(self._retries):
|
||||
try:
|
||||
self._log.debug('Connection attempt {}...'.format(retry))
|
||||
self._log.debug('Connection attempt {}...'.format(attempt))
|
||||
await self._connection.connect(timeout=self._connect_timeout)
|
||||
except (ConnectionError, asyncio.TimeoutError) as e:
|
||||
self._log.warning('Attempt {} at connecting failed: {}: {}'
|
||||
.format(retry, type(e).__name__, e))
|
||||
.format(attempt, type(e).__name__, e))
|
||||
await asyncio.sleep(self._delay)
|
||||
else:
|
||||
break
|
||||
else:
|
||||
raise ConnectionError('Connection to Telegram failed {} times'
|
||||
.format(self._retries))
|
||||
raise ConnectionError('Connection to Telegram failed {} time(s)'
|
||||
.format(attempt))
|
||||
|
||||
self._log.debug('Connection success!')
|
||||
if not self.auth_key:
|
||||
plain = MTProtoPlainSender(self._connection, loggers=self._loggers)
|
||||
for retry in range(1, self._retries + 1):
|
||||
for attempt in retry_range(self._retries):
|
||||
try:
|
||||
self._log.debug('New auth_key attempt {}...'.format(retry))
|
||||
self._log.debug('New auth_key attempt {}...'
|
||||
.format(attempt))
|
||||
self.auth_key.key, self._state.time_offset =\
|
||||
await authenticator.do_authentication(plain)
|
||||
|
||||
|
@ -244,11 +246,11 @@ class MTProtoSender:
|
|||
break
|
||||
except (SecurityError, AssertionError) as e:
|
||||
self._log.warning('Attempt {} at new auth_key failed: {}'
|
||||
.format(retry, e))
|
||||
.format(attempt, e))
|
||||
await asyncio.sleep(self._delay)
|
||||
else:
|
||||
e = ConnectionError('auth_key generation failed {} times'
|
||||
.format(self._retries))
|
||||
e = ConnectionError('auth_key generation failed {} time(s)'
|
||||
.format(attempt))
|
||||
self._disconnect(error=e)
|
||||
raise e
|
||||
|
||||
|
@ -321,17 +323,17 @@ class MTProtoSender:
|
|||
self._state.reset()
|
||||
|
||||
retries = self._retries if self._auto_reconnect else 0
|
||||
for retry in range(1, retries + 1):
|
||||
for attempt in retry_range(retries):
|
||||
try:
|
||||
await self._connect()
|
||||
except (ConnectionError, asyncio.TimeoutError) as e:
|
||||
self._log.info('Failed reconnection retry %d/%d with %s',
|
||||
retry, retries, e.__class__.__name__)
|
||||
self._log.info('Failed reconnection attempt %d with %s',
|
||||
attempt, e.__class__.__name__)
|
||||
|
||||
await asyncio.sleep(self._delay)
|
||||
except Exception:
|
||||
self._log.exception('Unexpected exception reconnecting on '
|
||||
'retry %d/%d', retry, retries)
|
||||
'attempt %d', attempt)
|
||||
|
||||
await asyncio.sleep(self._delay)
|
||||
else:
|
||||
|
@ -343,7 +345,8 @@ class MTProtoSender:
|
|||
|
||||
break
|
||||
else:
|
||||
self._log.error('Failed to reconnect automatically.')
|
||||
self._log.error('Automatic reconnection failed {} time(s)'
|
||||
.format(attempt))
|
||||
self._disconnect(error=ConnectionError())
|
||||
|
||||
def _start_reconnect(self):
|
||||
|
|
Loading…
Reference in New Issue
Block a user