Skip to content

Commit a9e7d15

Browse files
committed
Add a watchdog for incoming updates
1 parent aeea07f commit a9e7d15

3 files changed

Lines changed: 35 additions & 0 deletions

File tree

pyrogram/client.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import shutil
2727
import sys
2828
from concurrent.futures.thread import ThreadPoolExecutor
29+
from datetime import datetime, timedelta
2930
from hashlib import sha256
3031
from importlib import import_module
3132
from io import StringIO, BytesIO
@@ -185,6 +186,9 @@ class Client(Methods):
185186
WORKERS = min(32, (os.cpu_count() or 0) + 4) # os.cpu_count() can be None
186187
WORKDIR = PARENT_DIR
187188

189+
# Interval of seconds in which the updates watchdog will kick in
190+
UPDATES_WATCHDOG_INTERVAL = 5 * 60
191+
188192
mimetypes = MimeTypes()
189193
mimetypes.readfp(StringIO(mime_types))
190194

@@ -273,6 +277,13 @@ def __init__(
273277

274278
self.message_cache = Cache(10000)
275279

280+
# Sometimes, for some reason, the server will stop sending updates and will only respond to pings.
281+
# This watchdog will invoke updates.GetState in order to wake up the server and enable it sending updates again
282+
# after some idle time has been detected.
283+
self.updates_watchdog_task = None
284+
self.updates_watchdog_event = asyncio.Event()
285+
self.last_update_time = datetime.now()
286+
276287
self.loop = asyncio.get_event_loop()
277288

278289
def __enter__(self):
@@ -293,6 +304,18 @@ async def __aexit__(self, *args):
293304
except ConnectionError:
294305
pass
295306

307+
async def updates_watchdog(self):
308+
while True:
309+
try:
310+
await asyncio.wait_for(self.updates_watchdog_event.wait(), self.UPDATES_WATCHDOG_INTERVAL)
311+
except asyncio.TimeoutError:
312+
pass
313+
else:
314+
break
315+
316+
if datetime.now() - self.last_update_time > timedelta(seconds=self.UPDATES_WATCHDOG_INTERVAL):
317+
await self.invoke(raw.functions.updates.GetState())
318+
296319
async def authorize(self) -> User:
297320
if self.bot_token:
298321
return await self.sign_in_bot(self.bot_token)
@@ -484,6 +507,8 @@ async def fetch_peers(self, peers: List[Union[raw.types.User, raw.types.Chat, ra
484507
return is_min
485508

486509
async def handle_updates(self, updates):
510+
self.last_update_time = datetime.now()
511+
487512
if isinstance(updates, (raw.types.Updates, raw.types.UpdatesCombined)):
488513
is_min = any((
489514
await self.fetch_peers(updates.users),

pyrogram/methods/auth/initialize.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
# You should have received a copy of the GNU Lesser General Public License
1717
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
1818

19+
import asyncio
1920
import logging
2021

2122
import pyrogram
@@ -46,4 +47,6 @@ async def initialize(
4647

4748
await self.dispatcher.start()
4849

50+
self.updates_watchdog_task = asyncio.create_task(self.updates_watchdog())
51+
4952
self.is_initialized = True

pyrogram/methods/auth/terminate.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,11 @@ async def terminate(
5151

5252
self.media_sessions.clear()
5353

54+
self.updates_watchdog_event.set()
55+
56+
if self.updates_watchdog_task is not None:
57+
await self.updates_watchdog_task
58+
59+
self.updates_watchdog_event.clear()
60+
5461
self.is_initialized = False

0 commit comments

Comments
 (0)