mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2025-06-17 10:36:37 +00:00
Stop using *args when invoking many requests at once
This commit is contained in:
parent
e200acbca8
commit
e2e7e631b5
@ -5,7 +5,7 @@ encrypting every packet, and relies on a valid AuthKey in the used Session.
|
|||||||
import logging
|
import logging
|
||||||
from threading import Lock
|
from threading import Lock
|
||||||
|
|
||||||
from .. import helpers as utils
|
from .. import helpers, utils
|
||||||
from ..errors import (
|
from ..errors import (
|
||||||
BadMessageError, InvalidChecksumError, BrokenAuthKeyError,
|
BadMessageError, InvalidChecksumError, BrokenAuthKeyError,
|
||||||
rpc_message_to_error
|
rpc_message_to_error
|
||||||
@ -84,7 +84,7 @@ class MtProtoSender:
|
|||||||
|
|
||||||
# region Send and receive
|
# region Send and receive
|
||||||
|
|
||||||
def send(self, *requests, ordered=False):
|
def send(self, requests, ordered=False):
|
||||||
"""
|
"""
|
||||||
Sends the specified TLObject(s) (which must be requests),
|
Sends the specified TLObject(s) (which must be requests),
|
||||||
and acknowledging any message which needed confirmation.
|
and acknowledging any message which needed confirmation.
|
||||||
@ -94,6 +94,9 @@ class MtProtoSender:
|
|||||||
order in which they appear or they can be executed
|
order in which they appear or they can be executed
|
||||||
in arbitrary order in the server.
|
in arbitrary order in the server.
|
||||||
"""
|
"""
|
||||||
|
if not utils.is_list_like(requests):
|
||||||
|
requests = (requests,)
|
||||||
|
|
||||||
if ordered:
|
if ordered:
|
||||||
requests = iter(requests)
|
requests = iter(requests)
|
||||||
messages = [TLMessage(self.session, next(requests))]
|
messages = [TLMessage(self.session, next(requests))]
|
||||||
@ -184,7 +187,7 @@ class MtProtoSender:
|
|||||||
:param message: the TLMessage to be sent.
|
:param message: the TLMessage to be sent.
|
||||||
"""
|
"""
|
||||||
with self._send_lock:
|
with self._send_lock:
|
||||||
self.connection.send(utils.pack_message(self.session, message))
|
self.connection.send(helpers.pack_message(self.session, message))
|
||||||
|
|
||||||
def _decode_msg(self, body):
|
def _decode_msg(self, body):
|
||||||
"""
|
"""
|
||||||
@ -200,7 +203,7 @@ class MtProtoSender:
|
|||||||
raise BufferError("Can't decode packet ({})".format(body))
|
raise BufferError("Can't decode packet ({})".format(body))
|
||||||
|
|
||||||
with BinaryReader(body) as reader:
|
with BinaryReader(body) as reader:
|
||||||
return utils.unpack_message(self.session, reader)
|
return helpers.unpack_message(self.session, reader)
|
||||||
|
|
||||||
def _process_msg(self, msg_id, sequence, reader, state):
|
def _process_msg(self, msg_id, sequence, reader, state):
|
||||||
"""
|
"""
|
||||||
|
@ -429,32 +429,51 @@ class TelegramBareClient:
|
|||||||
|
|
||||||
# region Invoking Telegram requests
|
# region Invoking Telegram requests
|
||||||
|
|
||||||
def __call__(self, *requests, retries=5, ordered=False):
|
def __call__(self, request, retries=5, ordered=False):
|
||||||
"""Invokes (sends) a MTProtoRequest and returns (receives) its result.
|
|
||||||
|
|
||||||
The invoke will be retried up to 'retries' times before raising
|
|
||||||
RuntimeError().
|
|
||||||
|
|
||||||
If more than one request is given and ordered is True, then the
|
|
||||||
requests will be invoked sequentially in the server (useful for
|
|
||||||
bursts of requests that need to be ordered).
|
|
||||||
"""
|
"""
|
||||||
|
Invokes (sends) one or more MTProtoRequests and returns (receives)
|
||||||
|
their result.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request (`TLObject` | `list`):
|
||||||
|
The request or requests to be invoked.
|
||||||
|
|
||||||
|
retries (`bool`, optional):
|
||||||
|
How many times the request should be retried automatically
|
||||||
|
in case it fails with a non-RPC error.
|
||||||
|
|
||||||
|
The invoke will be retried up to 'retries' times before raising
|
||||||
|
``RuntimeError``.
|
||||||
|
|
||||||
|
ordered (`bool`, optional):
|
||||||
|
Whether the requests (if more than one was given) should be
|
||||||
|
executed sequentially on the server. They run in arbitrary
|
||||||
|
order by default.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The result of the request (often a `TLObject`) or a list of
|
||||||
|
results if more than one request was given.
|
||||||
|
"""
|
||||||
|
single = not utils.is_list_like(request)
|
||||||
|
if single:
|
||||||
|
request = (request,)
|
||||||
|
|
||||||
if not all(isinstance(x, TLObject) and
|
if not all(isinstance(x, TLObject) and
|
||||||
x.content_related for x in requests):
|
x.content_related for x in request):
|
||||||
raise TypeError('You can only invoke requests, not types!')
|
raise TypeError('You can only invoke requests, not types!')
|
||||||
|
|
||||||
if self._background_error:
|
if self._background_error:
|
||||||
raise self._background_error
|
raise self._background_error
|
||||||
|
|
||||||
for request in requests:
|
for r in request:
|
||||||
request.resolve(self, utils)
|
r.resolve(self, utils)
|
||||||
|
|
||||||
# For logging purposes
|
# For logging purposes
|
||||||
if len(requests) == 1:
|
if single:
|
||||||
which = type(requests[0]).__name__
|
which = type(request[0]).__name__
|
||||||
else:
|
else:
|
||||||
which = '{} requests ({})'.format(
|
which = '{} requests ({})'.format(
|
||||||
len(requests), [type(x).__name__ for x in requests])
|
len(request), [type(x).__name__ for x in request])
|
||||||
|
|
||||||
# Determine the sender to be used (main or a new connection)
|
# Determine the sender to be used (main or a new connection)
|
||||||
__log__.debug('Invoking %s', which)
|
__log__.debug('Invoking %s', which)
|
||||||
@ -462,13 +481,13 @@ class TelegramBareClient:
|
|||||||
not self._idling.is_set() or self._reconnect_lock.locked()
|
not self._idling.is_set() or self._reconnect_lock.locked()
|
||||||
|
|
||||||
for retry in range(retries):
|
for retry in range(retries):
|
||||||
result = self._invoke(call_receive, *requests, ordered=ordered)
|
result = self._invoke(call_receive, request, ordered=ordered)
|
||||||
if result is not None:
|
if result is not None:
|
||||||
return result
|
return result[0] if single else result
|
||||||
|
|
||||||
log = __log__.info if retry == 0 else __log__.warning
|
log = __log__.info if retry == 0 else __log__.warning
|
||||||
log('Invoking %s failed %d times, connecting again and retrying',
|
log('Invoking %s failed %d times, connecting again and retrying',
|
||||||
[str(x) for x in requests], retry + 1)
|
which, retry + 1)
|
||||||
|
|
||||||
sleep(1)
|
sleep(1)
|
||||||
# The ReadThread has priority when attempting reconnection,
|
# The ReadThread has priority when attempting reconnection,
|
||||||
@ -479,13 +498,13 @@ class TelegramBareClient:
|
|||||||
self._reconnect()
|
self._reconnect()
|
||||||
|
|
||||||
raise RuntimeError('Number of retries reached 0 for {}.'.format(
|
raise RuntimeError('Number of retries reached 0 for {}.'.format(
|
||||||
[type(x).__name__ for x in requests]
|
which
|
||||||
))
|
))
|
||||||
|
|
||||||
# Let people use client.invoke(SomeRequest()) instead client(...)
|
# Let people use client.invoke(SomeRequest()) instead client(...)
|
||||||
invoke = __call__
|
invoke = __call__
|
||||||
|
|
||||||
def _invoke(self, call_receive, *requests, ordered=False):
|
def _invoke(self, call_receive, requests, ordered=False):
|
||||||
try:
|
try:
|
||||||
# Ensure that we start with no previous errors (i.e. resending)
|
# Ensure that we start with no previous errors (i.e. resending)
|
||||||
for x in requests:
|
for x in requests:
|
||||||
@ -510,7 +529,7 @@ class TelegramBareClient:
|
|||||||
self._wrap_init_connection(GetConfigRequest())
|
self._wrap_init_connection(GetConfigRequest())
|
||||||
)
|
)
|
||||||
|
|
||||||
self._sender.send(*requests, ordered=ordered)
|
self._sender.send(requests, ordered=ordered)
|
||||||
|
|
||||||
if not call_receive:
|
if not call_receive:
|
||||||
# TODO This will be slightly troublesome if we allow
|
# TODO This will be slightly troublesome if we allow
|
||||||
@ -566,10 +585,7 @@ class TelegramBareClient:
|
|||||||
# rejected by the other party as a whole."
|
# rejected by the other party as a whole."
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if len(requests) == 1:
|
return [x.result for x in requests]
|
||||||
return requests[0].result
|
|
||||||
else:
|
|
||||||
return [x.result for x in requests]
|
|
||||||
|
|
||||||
except (PhoneMigrateError, NetworkMigrateError,
|
except (PhoneMigrateError, NetworkMigrateError,
|
||||||
UserMigrateError) as e:
|
UserMigrateError) as e:
|
||||||
|
@ -1367,10 +1367,7 @@ class TelegramClient(TelegramBareClient):
|
|||||||
if requests[0].offset > limit:
|
if requests[0].offset > limit:
|
||||||
break
|
break
|
||||||
|
|
||||||
if len(requests) == 1:
|
results = self(requests)
|
||||||
results = (self(requests[0]),)
|
|
||||||
else:
|
|
||||||
results = self(*requests)
|
|
||||||
for i in reversed(range(len(requests))):
|
for i in reversed(range(len(requests))):
|
||||||
participants = results[i]
|
participants = results[i]
|
||||||
if not participants.users:
|
if not participants.users:
|
||||||
|
Loading…
Reference in New Issue
Block a user