Begin reworking update handling

Use a fixed-size queue instead of a callback to deal with updates.

Port the message box and entity cache from grammers to start off
with a clean design.

Temporarily get rid of other cruft such as automatic pings or old
catch up implementation.
This commit is contained in:
Lonami Exo
2022-01-18 19:46:19 +01:00
parent 3afabdd7c0
commit f6df5d377c
7 changed files with 704 additions and 315 deletions

View File

@@ -1,6 +1,7 @@
import asyncio
import collections
import struct
import logging
from . import authenticator
from .._misc.messagepacker import MessagePacker
@@ -20,6 +21,9 @@ from .._misc import helpers, utils
from .. import _tl
UPDATE_BUFFER_FULL_WARN_DELAY = 15 * 60
class MTProtoSender:
"""
MTProto Mobile Protocol sender
@@ -35,9 +39,8 @@ class MTProtoSender:
A new authorization key will be generated on connection if no other
key exists yet.
"""
def __init__(self, *, loggers,
retries=5, delay=1, auto_reconnect=True, connect_timeout=None,
update_callback=None):
def __init__(self, *, loggers, updates_queue,
retries=5, delay=1, auto_reconnect=True, connect_timeout=None,):
self._connection = None
self._loggers = loggers
self._log = loggers[__name__]
@@ -45,7 +48,7 @@ class MTProtoSender:
self._delay = delay
self._auto_reconnect = auto_reconnect
self._connect_timeout = connect_timeout
self._update_callback = update_callback
self._updates_queue = updates_queue
self._connect_lock = asyncio.Lock()
self._ping = None
@@ -83,6 +86,9 @@ class MTProtoSender:
# is received, but we may still need to resend their state on bad salts.
self._last_acks = collections.deque(maxlen=10)
# Last time we warned about the update buffer being full
self._last_update_warn = -UPDATE_BUFFER_FULL_WARN_DELAY
# Jump table from response ID to method that handles it
self._handlers = {
RpcResult.CONSTRUCTOR_ID: self._handle_rpc_result,
@@ -629,8 +635,16 @@ class MTProtoSender:
return
self._log.debug('Handling update %s', message.obj.__class__.__name__)
if self._update_callback:
self._update_callback(message.obj)
try:
self._updates_queue.put_nowait(message.obj)
except asyncio.QueueFull:
now = asyncio.get_running_loop().time()
if now - self._last_update_warn >= UPDATE_BUFFER_FULL_WARN_DELAY:
self._log.warning(
'Cannot dispatch update because the buffer capacity of %d was reached',
self._updates_queue.maxsize
)
self._last_update_warn = now
async def _handle_pong(self, message):
"""