DavFile async download

This commit is contained in:
Jörn-Michael Miehe 2022-08-31 10:20:54 +00:00
parent cfb813f787
commit d4158e37fb

View file

@ -1,3 +1,5 @@
import asyncio
import functools
import logging import logging
from io import BytesIO from io import BytesIO
from threading import Lock from threading import Lock
@ -9,6 +11,20 @@ from webdav3.client import Resource
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
def run_in_executor(f):
"""
Decorator to make blocking function call asyncio compatible
https://stackoverflow.com/questions/41063331/how-to-use-asyncio-with-existing-blocking-library/
"""
@functools.wraps(f)
def inner(*args, **kwargs):
loop = asyncio.get_running_loop()
return loop.run_in_executor(None, functools.partial(f, *args, **kwargs))
return inner
class DavFile: class DavFile:
__instances: Optional[list["DavFile"]] = None __instances: Optional[list["DavFile"]] = None
__scheduler = None __scheduler = None
@ -25,12 +41,17 @@ class DavFile:
if refresh: if refresh:
DavFile.__instances.append(self) DavFile.__instances.append(self)
def download(self) -> None: async def download(self) -> None:
@run_in_executor
def download_inner() -> None:
self.__resource.write_to(self.__buffer)
_logger.info(f"updating {self.__resource}") _logger.info(f"updating {self.__resource}")
with self.__lock: with self.__lock:
self.__buffer.seek(0) self.__buffer.seek(0)
self.__buffer.truncate(0) self.__buffer.truncate(0)
self.__resource.write_to(self.__buffer) await download_inner()
@classmethod @classmethod
def refresh(cls, refresh_interval: int = 60) -> None: def refresh(cls, refresh_interval: int = 60) -> None:
@ -42,9 +63,9 @@ class DavFile:
) )
return return
def tick() -> None: async def tick() -> None:
for davfile in DavFile.__instances: for davfile in DavFile.__instances:
davfile.download() await davfile.download()
cls.__scheduler = AsyncIOScheduler() cls.__scheduler = AsyncIOScheduler()
cls.__scheduler.start() cls.__scheduler.start()