/pyrogram/syncer.py

https://github.com/pyrogram/pyrogram · Python · 88 lines · 54 code · 17 blank · 17 comment · 15 complexity · 6c35587096e3b20bda7ab0378386074c MD5 · raw file

  1. # Pyrogram - Telegram MTProto API Client Library for Python
  2. # Copyright (C) 2017-2020 Dan <https://github.com/delivrance>
  3. #
  4. # This file is part of Pyrogram.
  5. #
  6. # Pyrogram is free software: you can redistribute it and/or modify
  7. # it under the terms of the GNU Lesser General Public License as published
  8. # by the Free Software Foundation, either version 3 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # Pyrogram is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU Lesser General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU Lesser General Public License
  17. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
  18. import asyncio
  19. import logging
  20. import time
  21. log = logging.getLogger(__name__)
  22. class Syncer:
  23. INTERVAL = 20
  24. clients = {}
  25. event = None
  26. lock = None
  27. @classmethod
  28. async def add(cls, client):
  29. if cls.event is None:
  30. cls.event = asyncio.Event()
  31. if cls.lock is None:
  32. cls.lock = asyncio.Lock()
  33. async with cls.lock:
  34. await cls.sync(client)
  35. cls.clients[id(client)] = client
  36. if len(cls.clients) == 1:
  37. cls.start()
  38. @classmethod
  39. async def remove(cls, client):
  40. async with cls.lock:
  41. await cls.sync(client)
  42. del cls.clients[id(client)]
  43. if len(cls.clients) == 0:
  44. cls.stop()
  45. @classmethod
  46. def start(cls):
  47. cls.event.clear()
  48. asyncio.get_event_loop().create_task(cls.worker())
  49. @classmethod
  50. def stop(cls):
  51. cls.event.set()
  52. @classmethod
  53. async def worker(cls):
  54. while True:
  55. try:
  56. await asyncio.wait_for(cls.event.wait(), cls.INTERVAL)
  57. except asyncio.TimeoutError:
  58. async with cls.lock:
  59. for client in cls.clients.values():
  60. await cls.sync(client)
  61. else:
  62. break
  63. @classmethod
  64. async def sync(cls, client):
  65. try:
  66. start = time.time()
  67. await client.storage.save()
  68. except Exception as e:
  69. log.critical(e, exc_info=True)
  70. else:
  71. log.info(f'Synced "{client.storage.name}" in {(time.time() - start) * 1000:.6} ms')