[perf] Extension list cache (#3616)
This commit is contained in:
parent
ca94909aab
commit
ad268516a9
4 changed files with 45 additions and 2 deletions
|
|
@ -6,6 +6,7 @@ import json
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import zipfile
|
import zipfile
|
||||||
|
from asyncio.tasks import create_task
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
|
@ -20,6 +21,7 @@ from lnbits.helpers import (
|
||||||
version_parse,
|
version_parse,
|
||||||
)
|
)
|
||||||
from lnbits.settings import settings
|
from lnbits.settings import settings
|
||||||
|
from lnbits.utils.cache import cache
|
||||||
|
|
||||||
|
|
||||||
class ExplicitRelease(BaseModel):
|
class ExplicitRelease(BaseModel):
|
||||||
|
|
@ -606,6 +608,37 @@ class InstallableExtension(BaseModel):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def get_installable_extensions(
|
async def get_installable_extensions(
|
||||||
|
cls, post_refresh_cache: bool = False
|
||||||
|
) -> list[InstallableExtension]:
|
||||||
|
extension_list: list[InstallableExtension] = []
|
||||||
|
|
||||||
|
cache_key = "extensions:installable"
|
||||||
|
cache_value = cache.value(cache_key)
|
||||||
|
if not cache_value:
|
||||||
|
extension_list = await cls._get_installable_extensions()
|
||||||
|
cache.set(cache_key, extension_list, expiry=3600) # one hour
|
||||||
|
return extension_list
|
||||||
|
|
||||||
|
if cache_value.older_than(10 * 60) or post_refresh_cache:
|
||||||
|
# refresh cache in background if older than 10 minutes or requested
|
||||||
|
create_task(cls._refresh_installable_extensions_cache())
|
||||||
|
|
||||||
|
extension_list = cache_value.value # type: ignore
|
||||||
|
return extension_list
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def _refresh_installable_extensions_cache(
|
||||||
|
cls,
|
||||||
|
) -> None:
|
||||||
|
cache_key = "extensions:installable"
|
||||||
|
extension_list: list[InstallableExtension] = (
|
||||||
|
await cls._get_installable_extensions()
|
||||||
|
)
|
||||||
|
|
||||||
|
cache.set(cache_key, extension_list, expiry=3600)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def _get_installable_extensions(
|
||||||
cls,
|
cls,
|
||||||
) -> list[InstallableExtension]:
|
) -> list[InstallableExtension]:
|
||||||
extension_list: list[InstallableExtension] = []
|
extension_list: list[InstallableExtension] = []
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,9 @@ async def run_by_the_minute_tasks() -> None:
|
||||||
if minute_counter % 60 == 0:
|
if minute_counter % 60 == 0:
|
||||||
try:
|
try:
|
||||||
# initialize the list of all extensions
|
# initialize the list of all extensions
|
||||||
await InstallableExtension.get_installable_extensions()
|
await InstallableExtension.get_installable_extensions(
|
||||||
|
post_refresh_cache=True
|
||||||
|
)
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
logger.error(ex)
|
logger.error(ex)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -508,7 +508,9 @@ async def extensions(account_id: AccountId = Depends(check_account_id_exists)):
|
||||||
installed_exts: list[InstallableExtension] = await get_installed_extensions()
|
installed_exts: list[InstallableExtension] = await get_installed_extensions()
|
||||||
installed_exts_ids = [e.id for e in installed_exts]
|
installed_exts_ids = [e.id for e in installed_exts]
|
||||||
|
|
||||||
installable_exts = await InstallableExtension.get_installable_extensions()
|
installable_exts = await InstallableExtension.get_installable_extensions(
|
||||||
|
post_refresh_cache=account_id.is_admin_id
|
||||||
|
)
|
||||||
installable_exts_ids = [e.id for e in installable_exts]
|
installable_exts_ids = [e.id for e in installable_exts]
|
||||||
installable_exts += [e for e in installed_exts if e.id not in installable_exts_ids]
|
installable_exts += [e for e in installed_exts if e.id not in installable_exts_ids]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,9 @@ class Cached(NamedTuple):
|
||||||
value: Any
|
value: Any
|
||||||
expiry: float
|
expiry: float
|
||||||
|
|
||||||
|
def older_than(self, seconds: float) -> bool:
|
||||||
|
return time() - self.expiry > seconds
|
||||||
|
|
||||||
|
|
||||||
class Cache:
|
class Cache:
|
||||||
"""
|
"""
|
||||||
|
|
@ -23,6 +26,9 @@ class Cache:
|
||||||
self.interval = interval
|
self.interval = interval
|
||||||
self._values: dict[Any, Cached] = {}
|
self._values: dict[Any, Cached] = {}
|
||||||
|
|
||||||
|
def value(self, key: str) -> Cached | None:
|
||||||
|
return self._values.get(key)
|
||||||
|
|
||||||
def get(self, key: str, default=None) -> Any | None:
|
def get(self, key: str, default=None) -> Any | None:
|
||||||
cached = self._values.get(key)
|
cached = self._values.get(key)
|
||||||
if cached is not None:
|
if cached is not None:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue