Stop using *args when invoking many requests at once

This commit is contained in:
Lonami Exo 2018-05-09 10:19:45 +02:00
parent e200acbca8
commit e2e7e631b5
3 changed files with 49 additions and 33 deletions

View File

@ -5,7 +5,7 @@ encrypting every packet, and relies on a valid AuthKey in the used Session.
import logging
from threading import Lock
from .. import helpers as utils
from .. import helpers, utils
from ..errors import (
BadMessageError, InvalidChecksumError, BrokenAuthKeyError,
rpc_message_to_error
@ -84,7 +84,7 @@ class MtProtoSender:
# 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),
and acknowledging any message which needed confirmation.
@ -94,6 +94,9 @@ class MtProtoSender:
order in which they appear or they can be executed
in arbitrary order in the server.
"""
if not utils.is_list_like(requests):
requests = (requests,)
if ordered:
requests = iter(requests)
messages = [TLMessage(self.session, next(requests))]
@ -184,7 +187,7 @@ class MtProtoSender:
:param message: the TLMessage to be sent.
"""
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):
"""
@ -200,7 +203,7 @@ class MtProtoSender:
raise BufferError("Can't decode packet ({})".format(body))
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):
"""

View File

@ -429,32 +429,51 @@ class TelegramBareClient:
# region Invoking Telegram requests
def __call__(self, *requests, 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).
def __call__(self, request, retries=5, ordered=False):
"""
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
x.content_related for x in requests):
x.content_related for x in request):
raise TypeError('You can only invoke requests, not types!')
if self._background_error:
raise self._background_error
for request in requests:
request.resolve(self, utils)
for r in request:
r.resolve(self, utils)
# For logging purposes
if len(requests) == 1:
which = type(requests[0]).__name__
if single:
which = type(request[0]).__name__
else:
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)
__log__.debug('Invoking %s', which)
@ -462,13 +481,13 @@ class TelegramBareClient:
not self._idling.is_set() or self._reconnect_lock.locked()
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:
return result
return result[0] if single else result
log = __log__.info if retry == 0 else __log__.warning
log('Invoking %s failed %d times, connecting again and retrying',
[str(x) for x in requests], retry + 1)
which, retry + 1)
sleep(1)
# The ReadThread has priority when attempting reconnection,
@ -479,13 +498,13 @@ class TelegramBareClient:
self._reconnect()
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(...)
invoke = __call__
def _invoke(self, call_receive, *requests, ordered=False):
def _invoke(self, call_receive, requests, ordered=False):
try:
# Ensure that we start with no previous errors (i.e. resending)
for x in requests:
@ -510,7 +529,7 @@ class TelegramBareClient:
self._wrap_init_connection(GetConfigRequest())
)
self._sender.send(*requests, ordered=ordered)
self._sender.send(requests, ordered=ordered)
if not call_receive:
# TODO This will be slightly troublesome if we allow
@ -566,10 +585,7 @@ class TelegramBareClient:
# rejected by the other party as a whole."
return None
if len(requests) == 1:
return requests[0].result
else:
return [x.result for x in requests]
return [x.result for x in requests]
except (PhoneMigrateError, NetworkMigrateError,
UserMigrateError) as e:

View File

@ -1367,10 +1367,7 @@ class TelegramClient(TelegramBareClient):
if requests[0].offset > limit:
break
if len(requests) == 1:
results = (self(requests[0]),)
else:
results = self(*requests)
results = self(requests)
for i in reversed(range(len(requests))):
participants = results[i]
if not participants.users: