fix redis keying and de/serializing
This commit is contained in:
parent
5524c4094b
commit
27de977bfe
3 changed files with 38 additions and 54 deletions
|
@ -1,17 +1,16 @@
|
|||
import functools
|
||||
import logging
|
||||
from datetime import datetime, timedelta
|
||||
from typing import cast
|
||||
|
||||
from asyncify import asyncify
|
||||
from cachetools import TTLCache, cachedmethod
|
||||
from cachetools import cachedmethod
|
||||
from caldav import Calendar, DAVClient, Event, Principal
|
||||
from vobject.base import Component, toVName
|
||||
|
||||
from ..calevent import CalEvent
|
||||
from ..config import Config
|
||||
from ..settings import SETTINGS
|
||||
from .webdav import davkey
|
||||
from .helpers import REDIS, RedisCache, davkey
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -23,9 +22,9 @@ class CalDAV:
|
|||
password=SETTINGS.caldav.password,
|
||||
)
|
||||
|
||||
_cache = TTLCache(
|
||||
_cache = RedisCache(
|
||||
cache=REDIS,
|
||||
ttl=SETTINGS.caldav.cache_ttl,
|
||||
maxsize=SETTINGS.caldav.cache_size,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
|
@ -40,10 +39,7 @@ class CalDAV:
|
|||
@classmethod
|
||||
@property
|
||||
@asyncify
|
||||
@cachedmethod(
|
||||
cache=lambda cls: cls._cache,
|
||||
key=functools.partial(davkey, "calendars"),
|
||||
)
|
||||
@cachedmethod(cache=lambda cls: cls._cache, key=davkey("calendars"))
|
||||
def calendars(cls) -> list[str]:
|
||||
"""
|
||||
Asynchroneously lists all calendars using the main WebDAV client.
|
||||
|
@ -54,10 +50,7 @@ class CalDAV:
|
|||
|
||||
@classmethod
|
||||
@asyncify
|
||||
@cachedmethod(
|
||||
cache=lambda cls: cls._cache,
|
||||
key=functools.partial(davkey, "get_calendar"),
|
||||
)
|
||||
@cachedmethod(cache=lambda cls: cls._cache, key=davkey("get_calendar"))
|
||||
def get_calendar(cls, calendar_name: str) -> Calendar:
|
||||
"""
|
||||
Get a calendar by name using the CalDAV principal object.
|
||||
|
@ -67,10 +60,7 @@ class CalDAV:
|
|||
|
||||
@classmethod
|
||||
@asyncify
|
||||
@cachedmethod(
|
||||
cache=lambda cls: cls._cache,
|
||||
key=functools.partial(davkey, "get_events"),
|
||||
)
|
||||
@cachedmethod(cache=lambda cls: cls._cache, key=davkey("get_events", slice(1, 2)))
|
||||
def get_events(cls, calendar_name: str, cfg: Config) -> list[CalEvent]:
|
||||
"""
|
||||
Get a sorted list of events by CalDAV calendar name.
|
||||
|
|
|
@ -1,19 +1,29 @@
|
|||
from json import JSONDecodeError
|
||||
import pickle
|
||||
from typing import Callable, Hashable
|
||||
|
||||
import requests
|
||||
from cachetools.keys import hashkey
|
||||
from CacheToolsUtils import RedisCache as __RedisCache
|
||||
from redis import Redis
|
||||
from redis.commands.core import ResponseT
|
||||
from redis.typing import EncodableT
|
||||
from webdav3.client import Client as __WebDAVclient
|
||||
|
||||
from ..settings import SETTINGS
|
||||
|
||||
def davkey(name, _, *args, **kwargs):
|
||||
|
||||
def davkey(
|
||||
name: str,
|
||||
slice: slice = slice(1, None),
|
||||
) -> Callable[..., tuple[Hashable, ...]]:
|
||||
def func(*args, **kwargs) -> tuple[Hashable, ...]:
|
||||
"""Return a cache key for use with cached methods."""
|
||||
|
||||
key = hashkey(name, *args, **kwargs)
|
||||
key = hashkey(name, *args[slice], **kwargs)
|
||||
return hashkey(*(str(key_item) for key_item in key))
|
||||
|
||||
return func
|
||||
|
||||
|
||||
class WebDAVclient(__WebDAVclient):
|
||||
def execute_request(
|
||||
|
@ -39,16 +49,16 @@ class RedisCache(__RedisCache):
|
|||
"""
|
||||
|
||||
def _serialize(self, s) -> EncodableT:
|
||||
if isinstance(s, bytes):
|
||||
return s
|
||||
|
||||
else:
|
||||
return super()._serialize(s)
|
||||
return pickle.dumps(s)
|
||||
|
||||
def _deserialize(self, s: ResponseT):
|
||||
try:
|
||||
return super()._deserialize(s)
|
||||
|
||||
except (UnicodeDecodeError, JSONDecodeError):
|
||||
assert isinstance(s, bytes)
|
||||
return s
|
||||
return pickle.loads(s)
|
||||
|
||||
|
||||
REDIS = Redis(
|
||||
host=SETTINGS.redis.host,
|
||||
port=SETTINGS.redis.port,
|
||||
db=SETTINGS.redis.db,
|
||||
protocol=SETTINGS.redis.protocol,
|
||||
)
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
import functools
|
||||
import logging
|
||||
import re
|
||||
from io import BytesIO
|
||||
|
||||
from asyncify import asyncify
|
||||
from cachetools import cachedmethod
|
||||
from redis import Redis
|
||||
|
||||
from ..settings import SETTINGS
|
||||
from .helpers import RedisCache, WebDAVclient, davkey
|
||||
from .helpers import REDIS, RedisCache, WebDAVclient, davkey
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -23,21 +21,13 @@ class WebDAV:
|
|||
)
|
||||
|
||||
_cache = RedisCache(
|
||||
cache=Redis(
|
||||
host=SETTINGS.redis.host,
|
||||
port=SETTINGS.redis.port,
|
||||
db=SETTINGS.redis.db,
|
||||
protocol=SETTINGS.redis.protocol,
|
||||
),
|
||||
cache=REDIS,
|
||||
ttl=SETTINGS.webdav.cache_ttl,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
@asyncify
|
||||
@cachedmethod(
|
||||
cache=lambda cls: cls._cache,
|
||||
key=functools.partial(davkey, "list_files"),
|
||||
)
|
||||
@cachedmethod(cache=lambda cls: cls._cache, key=davkey("list_files"))
|
||||
def list_files(
|
||||
cls,
|
||||
directory: str = "",
|
||||
|
@ -55,10 +45,7 @@ class WebDAV:
|
|||
|
||||
@classmethod
|
||||
@asyncify
|
||||
@cachedmethod(
|
||||
cache=lambda cls: cls._cache,
|
||||
key=functools.partial(davkey, "exists"),
|
||||
)
|
||||
@cachedmethod(cache=lambda cls: cls._cache, key=davkey("exists"))
|
||||
def exists(cls, path: str) -> bool:
|
||||
"""
|
||||
`True` iff there is a WebDAV resource at `path`
|
||||
|
@ -69,10 +56,7 @@ class WebDAV:
|
|||
|
||||
@classmethod
|
||||
@asyncify
|
||||
@cachedmethod(
|
||||
cache=lambda cls: cls._cache,
|
||||
key=functools.partial(davkey, "read_bytes"),
|
||||
)
|
||||
@cachedmethod(cache=lambda cls: cls._cache, key=davkey("read_bytes"))
|
||||
def read_bytes(cls, path: str) -> bytes:
|
||||
"""
|
||||
Load WebDAV file from `path` as bytes
|
||||
|
@ -105,7 +89,7 @@ class WebDAV:
|
|||
cls._webdav_client.upload_to(buffer, path)
|
||||
|
||||
# invalidate cache entry
|
||||
cls._cache.pop(davkey("read_bytes", None, path))
|
||||
cls._cache.pop(davkey("read_bytes")(path))
|
||||
|
||||
@classmethod
|
||||
async def write_str(cls, path: str, content: str, encoding="utf-8") -> None:
|
||||
|
|
Loading…
Reference in a new issue